這題給出的圖的行列範圍較小,所以可以暴力來做。
要解決的問題就是怎樣方便的枚舉完所有可能的情況,並且得到放置blockhouse的最大值。
這要在dfs上下功夫了。
代碼中的dfs原型為dfs(int i,int num)。其中 i 為記錄該次搜尋已經到達那一個點了(i=1、2、...、n*n ,
表示從左至右、從上到下給每個點編號)。num是用來記錄當前搜尋已經添加的blockhouse數目,另
一個功能就是當本次搜尋結束,也就是i==n*n時,和全域變數maxNum比較並保留最大值放在maxNum
中。這樣當所有情況都搜完後,maxNum要求值了。
還有一些小細節:
1、canPlace(int row,int col) 用來判斷當前點 (row,col) 所在行列是否已經放置可以攻擊到該點的blockhouse。
2、如果當前點可以放置blockhouse則標記為 'o' 表示已放。當然也可以開一個二維數組visit[][]來標記。方法
不一。
AC代碼:
#include<iostream>using namespace std;const int MAX=4;char map[MAX][MAX];int n,maxNum; void storeMap() //存圖{for(int i=0;i<n;i++)cin>>map[i];}bool canPlace(int row,int col) //判斷是否可以放置{ //在遇到牆之前同行或同列上已放置,則不能再放int i;for(i=col-1;i>=0;i--){if(map[row][i]=='o') return false;if(map[row][i]=='X') break;}for(i=row-1;i>=0;i--){if(map[i][col]=='o') return false;if(map[i][col]=='X') break;}return true;}void dfs(int i,int num) //深搜,i代表已經搜尋到的點,num代表該次搜尋可以放得最多blockhouse{ //搜尋完所有可能情況,每點'.'都會作為起點搜尋一遍int row,col;if(i==n*n){if(num>maxNum) maxNum=num; //比較每遍搜尋結果,保留當前最大值return;}else{row=i/n; //從左至右,從上到下依次給每個點編號,1、2、...、n*ncol=i%n; //這是在取當前點所在圖的行和列if(map[row][col]=='.' && canPlace(row,col)){map[row][col]='o';dfs(i+1,num+1);map[row][col]='.';}dfs(i+1,num);}}int main(){while(cin>>n,n){storeMap();maxNum=0;dfs(0,0);cout<<maxNum<<endl;}return 0;}