簡單搜尋 POJ 1321棋盤問題 詳解

2021-10-25 00:09:48 字數 1658 閱讀 2398

棋盤問題:

在乙個給定形狀的棋盤(形狀可能是不規則的)上面擺放棋子,棋子沒有區別。要求擺放時任意的兩個棋子不能放在棋盤中的同一行或者同一列,請程式設計求解對於給定形狀和大小的棋盤,擺放k個棋子的所有可行的擺放方案c。

input:

輸入含有多組測試資料。

每組資料的第一行是兩個正整數,n k,用乙個空格隔開,表示了將在乙個n*n的矩陣內描述棋盤,以及擺放棋子的數目。 n <= 8 , k <= n

當為-1 -1時表示輸入結束。

隨後的n行描述了棋盤的形狀:每行有n個字元,其中 # 表示棋盤區域, . 表示空白區域(資料保證不出現多餘的空白行或者空白列)。

output:

對於每一組資料,給出一行輸出,輸出擺放的方案數目c (資料保證c<2^31)。

簡單的回溯搜尋(類似經典的八皇后問題)。

這題要得到方案數,因為找不到任何規律,所以只能去列舉所有可行的情況,並統計個數。而通過搜尋來列舉是一種比較高效的辦法。

1)首先建立全域性的陣列來存放棋盤:

int chessboard[10][10];    //0表示不能放棋子  1表示可以  2表示已經放了棋子
棋盤上的點顯然有三種可能的狀態:

①不能放棋子(即空白區域)

②可以放棋子

③可以放棋子但已經放過棋子了

分別用0,1,2記錄棋盤上點的狀態

2)寫乙個check函式來判斷某個棋盤上的點能不能放棋子

因為資料量較小,直接遍歷整個棋盤看看有沒有同一行或者同一列的棋子

bool check(int row,int column)
接著就是遞迴回溯。

第乙個變數row的設定目的是按序搜尋以避免答案重複

第二個變數step是為了記錄已經放置了幾顆棋子,當放了k個就結束搜尋,答案++

關於回溯,我是這麼理解的:

由於遞迴函式的性質,當向下一層繼續深蒐時,函式會「放下」當前的函式,先繼續往下一層深搜,等到下一層搜尋完畢之後再回到當前的函式。

以這道題為例,我們選擇乙個地方放置棋子,要對其進行標記,然後向下一層深搜。回溯的意思就是,當返回到當前函式後,解除這個標記。因為遞迴函式寫在for迴圈的內部,解除該標記後就可以去嘗試該行的下乙個位置了。

void dfs(int row,int step)

else}}

}

下附ac**:

#include using namespace std;

int n,k;

int chessboard[10][10]; //0表示不能放棋子 1表示可以 2表示已經放了棋子

int c;

bool check(int row,int column)

void dfs(int row,int step)

else}}

}int main()

dfs(1,0);

printf("%d\n",c);

}return 0;

}

POJ 1321棋盤問題 簡單搜尋

棋盤問題 crawling in process.crawling failed time limit 1000msmemory limit 10000kb64bit io format i64d i64u poj 1321 description 在乙個給定形狀的棋盤 形狀可能是不規則的 上面擺放...

POJ1321 棋盤問題(簡單搜尋)

在乙個給定形狀的棋盤 形狀可能是不規則的 上面擺放棋子,棋子沒有區別。要求擺放時任意的兩個棋子不能放在棋盤中的同一行或者同一列,請程式設計求解對於給定形狀和大小的棋盤,擺放k個棋子的所有可行的擺放方案c。input 輸入含有多組測試資料。每組資料的第一行是兩個正整數,n k,用乙個空格隔開,表示了將...

POJ1321 棋盤問題 簡單搜尋

棋盤問題 time limit 1000ms memory limit 10000k total submissions 67775 accepted 32273 description 在乙個給定形狀的棋盤 形狀可能是不規則的 上面擺放棋子,棋子沒有區別。要求擺放時任意的兩個棋子不能放在棋盤中的同...