程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> hdu 1045 貪心回溯

hdu 1045 貪心回溯

編輯:C++入門知識

第一次理解遞歸的含義,並且應用起來。如在這個題目裡,我一開始有好幾種想法,但都和自己手動模擬的不一樣。
大意:給出一個地圖,x表示牆,任何武器都不能穿過,.表示空地,在空地上可以建炮樓,每個炮樓都可以攻擊到東西南北方向上的炮樓,前提是不能有牆擋著,在各個炮樓不能相互攻擊的情況下,最多能建多少個炮樓。

---------------------------------------------------------

我們以測試數據

說明<==>就是等價的意思

2
..
..
為例,來簡單的解釋這個經典的問題。從dfs(0,0)開始,也就是讀取數據map[0][0],然後檢查它的上面和左邊有沒有b,顯然符合條件,接下來執行dfs(1,1)讀取map[0][1],由於map[0][0]已經是b了,所以不符合check==1,執行dfs(pos+1,sum)<==>dfs(2,1)檢查map[1][0],同樣由於map[0][0]已經是b,故check!=1,接著執行dfs(pos+1,sum)<==>dfs(3,1)檢查map[1][1],可以使check==1,故可以執行map[1][1]=b,dfs(pos+1,sum+1)<==>dfs(4,2),重點就在於這裡,這也是絕大多貪心算法的難點,當pos==4是,會執行第一個if操作,並把最大的sum值保留下來,這時我們的題目要求,然後就return ;這句話我是半天沒想明白,現在終於有點感覺了,這個if判斷是結束當前活動點,注意下一個活動點所必需的,還有我們要明白這個return語句返回到什麼位置,規則是從哪裡來回到哪裡去,dfs(4,2)是怎麼來的呢,是由於dfs(3,1)符合check==1而來的,所以return就返回到dfs(3,1),也就是說這次我計算機記住你了,你dfs(4,2)是一個大坑,是騙人的,那我就不考慮你的先決條件了(check==1),但沒有辦法啊,誰叫我是一根筋呢!那還得執行從dfs(3,1)到dfs(pos+1,sum)<==>dfs(4,1),哇,直接就可以比較pos==n,這裡1比2小,就忽略了,但還得返回return啊,這次熊孩子要跑哪去,你猜猜?還是上面的規則,從哪裡來到哪裡去,熊孩子就得長記性,dfs(3,1)的兩個子條件都不符合,故dfs(3,1)要返回到它來的地方dfs(2,1),但是dfs(2,1)的兩個子條件也都不符合,沒辦法它也得回去,dfs(2,1)是誰派出來的,當然是dfs(1,1)了,它自己本身同樣沒有什麼本事,還得找他的頭dfs(0,0),也就是說從dfs(4,1)一直返回到了dfs(0,0),並把map[0][0]有原來的"b"賦值為"."(這就是著名的回溯),接下來怎麼辦呢?聰明的讀者,自己想想。------執行dfs(pos+1,sum)<==>dfs(1,0),如此循環下去,最大的方案數已經存放在ans中了。

接下來是完整的copy大神的代碼,後面附有自己為了弄明白dfs過程的調試數據,對自己的理解很有幫助!

/*************************************************************************
     File Name: 1045.cpp
     Author: yubo
     Mail: [email protected] 
     Created Time: 2014年04月13日 星期日 22時26分40秒
     學習重點:
 ************************************************************************/

#include
#include
#include
using namespace std;
int ans;//標記個數
char map[10][10];
int n;
int check(int r,int c)
{
	int flag=1,i;
	for(i=r;i>=0;i--){//從[r][c]的上面開始查找
		if(map[i][c]=='X') break;
		if(map[i][c]=='b'){
			flag=0;
			break;
		}
	}
	for(i=c;i>=0;i--){//從[r][c]的左邊開始查找 
		if(map[r][i]=='X') break;
		if(map[r][i]=='b'){
			flag=0;
			break;
		}
	}
	return flag;

	
}
void dfs(int pos,int sum)
{
	int r=pos/n,c=pos%n;//計算所檢查的位置
//	printf("pos=%d sum=%d r=%d c=%d \t",pos,sum,r,c);
	if(pos==n*n){//什麼意思呢,感覺pos永遠不會和n*n相等阿
		if(sum>ans)//會的,這樣會把當前的活動點干死,執行這句dfs(pos+1,sum)
			ans=sum;
		return ;
	}
	if(map[r][c]=='.'){
		if(check(r,c)==1){//符合題目要求的話
			map[r][c]='b';//表示建立一個blockhouse
			dfs(pos+1,sum+1);//向下尋找,同時sum+1
			map[r][c]='.';//這裡我就不懂了,為什麼要添加這一步哪
//			printf("2r=%d 2pos=%d sum=%d\n",r,pos,sum);//有大用,這句話是回溯時恢復原來的狀態

		}
	}
	dfs(pos+1,sum);//只是pos移動,其他沒有變化
	
}
int main()
{
	//freopen("in.txt","r",stdin);
	int i;
	while(scanf("%d",&n),n){
		ans=0;
		memset(map,0,sizeof(map));
		for(i=0;i>map[i];
		dfs(0,0);
		printf("%d\n",ans);
	}
}
同樣以2

..

..

為測試數據

並輸出部分數據你可能有更深刻的理解

/*************************************************************************
     File Name: 1045.cpp
     Author: yubo
     Mail: [email protected] 
     Created Time: 2014年04月13日 星期日 22時26分40秒
     學習重點:
 ************************************************************************/

#include
#include
#include
using namespace std;
int ans;//標記個數
char map[10][10];
int n;
int check(int r,int c)
{
	int flag=1,i;
	for(i=r;i>=0;i--){//從[r][c]的上面開始查找
		if(map[i][c]=='X') break;
		if(map[i][c]=='b'){
			flag=0;
			break;
		}
	}
	for(i=c;i>=0;i--){//從[r][c]的左邊開始查找 
		if(map[r][i]=='X') break;
		if(map[r][i]=='b'){
			flag=0;
			break;
		}
	}
	return flag;

	
}
void dfs(int pos,int sum)
{
	int r=pos/n,c=pos%n;//計算所檢查的位置
	printf("pos=%d sum=%d r=%d c=%d \t",pos,sum,r,c);
	if(pos==n*n){//什麼意思呢,感覺pos永遠不會和n*n相等阿
		if(sum>ans)//會的,這樣會把當前的活動點干死,執行這句dfs(pos+1,sum)
			ans=sum;
		return ;
	}
	if(map[r][c]=='.'){
		if(check(r,c)==1){//符合題目要求的話
			map[r][c]='b';//表示建立一個blockhouse
			dfs(pos+1,sum+1);//向下尋找,同時sum+1
			map[r][c]='.';//這裡我就不懂了,為什麼要添加這一步哪
			printf("2r=%d 2pos=%d sum=%d\n",r,pos,sum);//有大用,這句話是回溯時恢復原來的狀態

		}
	}
	dfs(pos+1,sum);//只是pos移動,其他沒有變化
	//printf("pos=%d sum=%d\t",r,c);
}
int main()
{
	freopen("in.txt","r",stdin);
	int i;
	while(scanf("%d",&n),n){
		ans=0;
		memset(map,0,sizeof(map));
		for(i=0;i>map[i];
		dfs(0,0);
		printf("%d\n",ans);
	}
}
中間過程數據;
pos=0 sum=0 r=0 c=0 	pos=1 sum=1 r=0 c=1 	pos=2 sum=1 r=1 c=0 	pos=3 sum=1 r=1 c=1 	pos=4 sum=2 r=2 c=0 	2r=1 2pos=3 sum=1
pos=4 sum=1 r=2 c=0 	2r=0 2pos=0 sum=0
pos=1 sum=0 r=0 c=1 	pos=2 sum=1 r=1 c=0 	pos=3 sum=2 r=1 c=1 	pos=4 sum=2 r=2 c=0 	2r=1 2pos=2 sum=1
pos=3 sum=1 r=1 c=1 	pos=4 sum=1 r=2 c=0 	2r=0 2pos=1 sum=0
pos=2 sum=0 r=1 c=0 	pos=3 sum=1 r=1 c=1 	pos=4 sum=1 r=2 c=0 	2r=1 2pos=2 sum=0
pos=3 sum=0 r=1 c=1 	pos=4 sum=1 r=2 c=0 	2r=1 2pos=3 sum=0
pos=4 sum=0 r=2 c=0 	2




  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved