1. 程式人生 > >回溯演算法的應用:C語言中的堡壘問題(不要把換行符輸到數組裡QAQ)

回溯演算法的應用:C語言中的堡壘問題(不要把換行符輸到數組裡QAQ)

描述
城堡是一個4×4的方格,為了保衛城堡,現需要在某些格子裡修建一些堡壘。城堡中的某些格子是牆,其餘格子都是空格,堡壘只能建在空格里,每個堡壘都可以向上下左右四個方向射擊,如果兩個堡壘在同一行或同一列,且中間沒有牆相隔,則兩個堡壘都會把對方打掉。問對於給定的一種狀態,最多能夠修建幾個堡壘。
輸入
每個測例以一個整數n(1<=n<=4)開始,表示城堡的大小。接下來是n行字元每行n個,‘X’表示該位置是牆,‘.’表示該位置是空格。n等於0標誌輸入結束。
輸出
每個測例在單獨的一行輸出一個整數:最多修建堡壘的個數。
輸入樣例
4
.X..
….
XX..
….
2
XX
.X
3
.X.
X.X
.X.
3

.XX
.XX
4
….
….
….
….
0
輸出樣例
5
1
5
2
4

這道題的輸入很奇怪!!!很容易錯!!!
如果用兩個for迴圈和scanf一個個輸入字元,會把換行符輸入進去。
用一個for迴圈和gets一行一行輸入,也會把第一個n後面的換行符輸入進去。
所以還要在前面加一個getchar把第一個換行符存到temp變數中。
總之很坑QAQ

#include<stdio.h>
int output[100]={0};//儲存結果的陣列
int n;
int cnt=0;//用來記錄輸入了幾組資料,方便存出結果和輸出。
char cb[5][5];//城堡地圖
int bl[5][5];//放堡壘的地圖
//兩個地圖是重合的
void testout()//檢查建了多少個堡壘,記錄最大堡壘數。 
{ int sum=0; for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { if(bl[i][j]==1) sum++; //一共建了多少堡壘 } } if(sum>output[cnt]) output[cnt]=sum;//把最大堡壘數存在陣列output中 } int check(int m)//檢查此處是否能建堡壘 { int x=m/n; int y=m%n; if(bl[x][y]==0) return 1
;//沒有堡壘是一定符合要求的。直接返回1。 if(cb[x][y]=='X'&&bl[x][y]==1) return 0;//有牆的地方不能建堡壘 int flag1=1,flag2=1; for(int j=0;j<y;j++) { if(bl[x][j]==1) { flag1=0; for(int i=j+1;i<y;i++) { if(cb[x][i]=='X') flag1=1; } } } for(int j=0;j<x;j++) { if(bl[j][y]==1) { flag2=0; for(int i=j+1;i<x;i++) { if(cb[i][y]=='X') flag2=1; } } } //新建的堡壘必須和同一行或同一列的其他堡壘間相隔一堵牆 if(flag1==1&&flag2==1) { return 1; } else return 0; } void chengbao(int m) { if(m==n*n) { testout(); } int x=m/n; int y=m%n;//將一維數字轉換為二維陣列的座標 (從0開始) if(m<n*n) { for(int i=1;i>=0;i--) { bl[x][y]=i; if(check(m)==0) continue;//不符合要求則繼續取值或回溯至符合要求 else chengbao(m+1); //符合要求則繼續遞迴呼叫 } } } void print()//輸出 { for(int i=1;i<=cnt;i++) { printf("%d\n",output[i]); } } int main() { while(1)//輸入資料 { scanf("%d",&n); if(n==0) break; cnt++; char temp=getchar();//把n後面的換行符存進去,否則會存入cb陣列 for(int i=0;i<=n-1;i++) { gets(cb[i]); } chengbao(0);//每輸入完一組資料,進行一次運算 } print();//輸出結果 }