hdu 1045 貪心回溯
大意:給出一個地圖,x表示牆,任何武器都不能穿過,.表示空地,在空地上可以建炮樓,每個炮樓都可以攻擊到東西南北方向上的炮樓,前提是不能有牆擋著,在各個炮樓不能相互攻擊的情況下,最多能建多少個炮樓。
---------------------------------------------------------
我們以測試資料
說明<==>就是等價的意思
..
..
為例,來簡單的解釋這個經典的問題。從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過程的除錯資料,對自己的理解很有幫助!
同樣以2/************************************************************************* File Name: 1045.cpp Author: yubo Mail: [email protected] Created Time: 2014年04月13日 星期日 22時26分40秒 學習重點: ************************************************************************/ #include<cstring> #include<cstdio> #include<iostream> 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<n;i++) cin>>map[i]; dfs(0,0); printf("%d\n",ans); } }
..
..
為測試資料
並輸出部分資料你可能有更深刻的理解
中間過程資料;/************************************************************************* File Name: 1045.cpp Author: yubo Mail: [email protected] Created Time: 2014年04月13日 星期日 22時26分40秒 學習重點: ************************************************************************/ #include<cstring> #include<cstdio> #include<iostream> 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<n;i++) cin>>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
相關推薦
hdu 1045 貪心回溯
第一次理解遞迴的含義,並且應用起來。如在這個題目裡,我一開始有好幾種想法,但都和自己手動模擬的不一樣。 大意:給出一個地圖,x表示牆,任何武器都不能穿過,.表示空地,在空地上可以建炮樓,每個炮樓都可以攻擊到東西南北方向上的炮樓,前提是不能有牆擋著,在各個炮樓不能相互攻擊的情
hdu 1045 Fire Net(回溯搜尋)
搜尋,回溯!!!人的一生避免不了會犯一些小錯誤!!! 那麼犯錯錯誤可以回頭的!不可以一直錯下去的!!! #include<stdio.h> #include<string.h> int visit[10][10]; char map[10][10];
hdu 6180貪心
bsp urn end 時間排序 有一個 判斷 對比 efi 起點 題意:有m個工程,一臺機器在同一時間只能運行一個工程,告訴你每個工程的起始時間和結束時間,求出最少要多少個機器以及最小的機器總運行時間(機器開始了就不能停了,知道用完該臺機器才停止)。 題解:由於這裏可以
hdu 6188 貪心
ack make printf ace 順子 comment inf -s memset hdu 6188 Duizi and Shunzi 題意:求一個序列中對子和順子的數量。 tags:優先組成對子。對於1 2 3 3 4 5 這樣的先判一下。 #inc
【HDU-1045,Fire Net-純暴力簡單DFS】
n! closed 實現 problem 由於 gif open pan alt 原題鏈接:點擊! 大致題意:白塊表示可以放置炮臺的位置——每個炮臺可以攻擊到上下左右的直線上的炮臺(也就是說在它的上下左右直線上不可以再放置炮臺,避免引起互相攻擊),黑塊表示隔離墻的位置
hdu-6301-貪心
arch xtra ret sin title elements php continue earch Distinct Values Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K
hdu-6438-貪心
inf cat show col .cn 獲得 day 隊列 esc Buy and Resell Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Tot
【HDU - 1045】Fire Net (dfs 或二分圖)
題幹: Suppose that we have a square city with straight streets. A map of a city is a square board with n rows and n columns, each representing a str
hdu 1045 Fire Net 【二分圖匹配】
進行 col numbers res clu 意思 archive 多少 color <題目鏈接> <轉載於 >>> > 題目大意: 這題意思是給出一張圖,圖中‘X‘表示wall,‘.‘表示空地,可以放置炮臺,同一條直線上只
HDU - 1045 A - Fire Net
Fire Net Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 13947 &nb
HDU 1045 Fire Net 【連通塊的壓縮 二分圖匹配】
題目:http://acm.hdu.edu.cn/showproblem.php?pid=1045 Fire Net Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Jav
hdu 1045(dfs類似8皇后)
Fire Net Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 15746 &nb
HDU 1045 Fire Net 二分圖建圖
HDU 1045 題意: 在一個n*n地圖中,有許多可以擋住子彈的牆,問最多可以放幾個炮臺,是的炮臺不會相互損害。炮臺會向四面發射子彈。 思路: 把行列分開做,先處理行,把同一行中相互聯通的點縮成一個點。再處理列,同樣縮成一個點。然後把行列中,交點不是牆的點連一條邊。對這個圖跑網路流或者二分圖
dfs HDU 1045
Problem Description Suppose that we have a square city with straight streets. A map of a city is a square board with n rows and n columns, each repr
HDU 4864 貪心
要求:有n臺機器和m個任務,並且每臺機器和每個任務都帶有一個時間標記和一個等級標記,只有機器的兩個標記都大於任務時才能進行該任務。最大等級不超過100,完成一個任務獲得錢數為500*時間+2*等級。一臺機器一天只能完成一個任務,求完成最大任務數,若有多解,取賺錢數最多的。 方法
HDU 1045 Fire Net
題目連結:傳送門 Problem Description Suppose that we have a square city with straight streets. A map of a city is a square board with n rows and
HDU-1045 Fire Net
可以直接dfs暴搜,也可以轉化為二分圖匹配問題 每一行連續的片段可以縮為一個點,列上連續的片段也是,因為連續的片段最多放一個點 就分為行片段,列片段兩部分,他們的交點就是邊,求最大匹配就是最多可以放的點 dfs暴搜程式碼: #include<iostream&g
HDU 1009 貪心
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 96673 Accepted Submiss
HDU - 1789貪心
#include<iostream> #include<cstring> #include<cstdio> #include<string> #include<algorithm> #include<queue> #incl
hdu 1789 貪心 優先佇列
Problem Description Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lot of homework to do. Every teacher g