description
在乙個給定形狀的棋盤(形狀可能是不規則的)上面擺放棋子,棋子沒有區別。要求擺放時任意的兩個棋子不能放在棋盤中的同一行或者同一列,請程式設計求解對於給定形狀和大小的棋盤,擺放k個棋子的所有可行的擺放方案c。
input
輸入含有多組測試資料。
每組資料的第一行是兩個正整數,n k,用乙個空格隔開,表示了將在乙個n*n的矩陣內描述棋盤,以及擺放棋子的數目。 n <= 8 , k <= n
當為-1 -1時表示輸入結束。
隨後的n行描述了棋盤的形狀:每行有n個字元,其中 # 表示棋盤區域, . 表示空白區域(資料保證不出現多餘的空白行或者空白列)。
output
對於每一組資料,給出一行輸出,輸出擺放的方案數目c (資料保證c<2^31)。
sample input
2 1sample output#..#
4 4...#
..#.
.#..
#...
-1 -1
21
雖然只是一道很簡單的dfs,但是這應該算是我第一道真正意義上的dfs,大的框架是自己想出來的,但是**的實現以及遞迴的一些細節卻是參考解題報告的,自己的功力還是太弱。不過這道題也讓自己對dfs遞迴有了更深的理解。acm不易,且碼且珍惜吧。
摘了網上的一段話:
「遞迴的主要問題應該是思維的跨度,初學遞迴時總是喜歡去想細節,甚至腦子裡一步一步的跟蹤,這對於初學時是不應該的,很多初學者在不相信思維跨度時,也就不相信遞迴求解是正確的。
我感覺學遞迴最大的問題是信任思維的跨度,直接將前n-1前移了,再去移第n個,一下子移n-1個,我感覺就相當於移1個,只是一種跨度而已。」
希望自己能有所感悟。
解題思路:
當一枚棋子落在棋盤上之後,這一行與同一列都不能再落子,去除這一行,這一列,剩下的相當是乙個(n-1)*(n-1)的棋盤,落子規則與上次相同,所有每一步落子都有著相同的子結構,可以用遞迴結構來解決此問題。
思路很簡單,只需從第一行第乙個開始搜尋,如果該位置該列沒被標記且為棋盤,那麼在這裡放上棋子,並標記,因為每行每列不能衝突,所以搜尋下一行,比並且棋子數加1。每次搜尋之前先要判斷是否棋子已經用完,如果用完,記錄方案數加1,然後直接返回。直到所有搜尋全部完成,此時已得到全部方案數。
此題還需注意標記陣列僅僅標記某一列上是否有棋子,因為每次遞迴下一行,所以每一行不會有衝突,只需判斷這一列上是否有其他棋子。還要注意修改標記後遞迴回來要及時復原。
這道題自己wa了三次。第一次是dfs函式裡搜尋的順序錯了。應該是從下一行開始搜尋,我寫成了從當前棋子的位置處開始搜尋。第二次是判斷落子的條件,應該是任意兩個棋子都不在同一行或同一列,我寫成了和當前棋子不在同一行或同一列。第三次是main函式裡面每次迴圈找到第乙個棋子落子的位置時沒有將該列標記以及復原。
#include #include using namespace std;
int n,k,cnt;
char maze[10][10];
bool col[10];
void dfs(int a,int b,int c)
for(int i = a+1;i < n;i++)
for(int j = 0;j < n;j++)
if(maze[i][j] == '#' && !col[j])
}int main()
cout << cnt << endl;
}return 0;
}
網上的做法普遍是按行遞增來搜尋,在dfs函式裡兩次呼叫dfs函式,感覺比我自己的要簡潔一點。還有此題還可以進一步剪枝以提高效率,但是資料很小就偷懶沒有剪枝了。
POJ 1321 棋盤問題(棋盤DFS)
棋盤問題 思路 分層查詢,逐行深搜。注意k n時的處理。1 include 2 include 3 include 4 include 5 include 6 include 7 include 8 include 9 include 10 define ll long long 11 define...
POJ 1321 棋盤問題 DFS
題意 在乙個給定形狀的棋盤 形狀可能是不規則的 上面擺放棋子,棋子沒有區別。要求擺放時任意的兩個棋子不能放在棋盤中的同一行或者同一列,請程式設計求解對於給定形狀和大小的棋盤,擺放k個棋子的所有可行的擺放方案c。題解 include using namespace std define n 10 bo...
poj 1321 棋盤問題(DFS)
大概題意就是給你乙個棋盤,讓你放棋子,求在棋盤n n上的 放上k個棋子的所有情況的數目。要求擺放時任意的兩個棋子不能放在棋盤中的同一行或者同一列。深搜可以搜尋出所有答案。直接看 include includebool chess 9 9 bool vis col 9 int n,k,ans void...