【NOJ1006】【演算法實驗二】【回溯演算法】堡壘問題_方格類資料表示方法
阿新 • • 發佈:2018-12-12
1006.堡壘問題
時限:1000ms 記憶體限制:10000K 總時限:3000ms
描述
城堡是一個4×4的方格,為了保衛城堡,現需要在某些格子裡修建一些堡壘。城堡中的某些格子是牆,其餘格子都是空格,堡壘只能建在空格里,每個堡壘都可以向上下左右四個方向射擊,如果兩個堡壘在同一行或同一列,且中間沒有牆相隔,則兩個堡壘都會把對方打掉。問對於給定的一種狀態,最多能夠修建幾個堡壘。
輸入
每個測例以一個整數n(1<=n<=4)開始,表示城堡的大小。
接下來是n行字元每行n個,‘X’表示該位置是牆,‘.’表示該位置是空格。
n等於0標誌輸入結束。
輸出
每個測例在單獨的一行輸出一個整數:最多修建堡壘的個數。
#include <iostream> using namespace std; int n; //城堡大小 int a[4][4]; //城堡方格,1==牆,0==空,-1==堡壘 //左上角為方格[0,0] int mcnt; //最大堡壘個數 int cnt; //當前已建堡壘個數 void dfs(int m); //回溯深搜 bool ok(int i,int j); //判斷方格[i,j]能否放置堡壘 int main() { cin>>n; while(n){ char c; for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ cin>>c; if(c=='X') //牆 a[i][j]=1; else //空 a[i][j]=0; } } //初始化 mcnt=0; cnt=0; dfs(0); cout<<mcnt<<endl; cin>>n; } return 0; } void dfs(int m) //判斷序號為m的方格 { if(m==(n*n)){ //搜到最後一個方格 if(mcnt<cnt) //更新最大值 mcnt=cnt; } else{ int i=m/n; int j=m%n; if(ok(i,j)){ //若方格m內可以修建堡壘 a[i][j]=-1; cnt++; dfs(m+1); cnt--; a[i][j]=0; } dfs(m+1); } } //函式功能:判斷方格[i,j]內能否放置堡壘 //不能放置條件: //1.本方格是牆 //2.本方格的上方或左方有堡壘(中間無牆相隔) //因為是按序號順序搜尋方格,因此不必判斷下方或右方(還未放置,必無堡壘) bool ok(int i,int j) { int x,y; if(a[i][j]==1) return false; //本方格是牆 for(x=i-1,y=j;x>=0;x--){ //向上找 if(a[x][y]==1) break; if(a[x][y]==-1) return false; } for(x=i,y=j-1;y>=0;y--){ //向左找 if(a[x][y]==1) break; if(a[x][y]==-1) return false; } return true; }
【後記】
1.做了幾道回溯,深深感覺dfs簡直就是套路,裡面多半是下面這種格式:
if (m==n)
{......}
else
{.......}
2.既然演算法是套路,那麼麻煩主要在於如何表示資料
一般來說,方格類資料用二維陣列表示,每個方格有兩個名字:序號m和位置[ i , j ]
預設左上角為序號0,位置為[ 0 , 0 ],如下圖所示: