传送门:POJ1321
首先注意POJ不认<bits/stdc++.h>…orz CE一发。
这道题最开始搜索搜的很混乱,看了八皇后再回来写。写棋盘搜索还是要先考虑剪枝,不是是棋盘搜索就一定dfs(int x, int y)这样搜的。比如八皇后和这道题,既然已知每行只有一个棋子,其实就可以只把行设为参数dfs(int row),不但会简化问题,写起来也不会头晕(省下了step部分的一坨……)。
我们在每次操作的时候要判断的其实只有两点(行固定的情况下):
- 该位置是否是’#’,即是否可以放棋子(在读入棋盘的时候就进行判断,更新available[][]数组)
- 行固定的情况下判断该列是否已经有棋子(通过colmark[]数组)
那么还有一个问题,因为N皇后问题那里是给我们N*N棋盘放N个棋子,所以每一行必然都会有一个棋子。但是,这道题不一定,很可能出现有10行但是只要放3个棋子的情况;并且还有可能我们虽然这一行不能放(均为’.’),但是因为行数远远多于要求棋子的数目,所以可以在后面的行中放棋子。也就是说,八皇后里面我们的判断和dfs是在一起的,但是这里判断成功后dfs,判断不成功其实也要dfs!!不然是没法扫完全的。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define ll long long
int n, k, ans;//n <= 8 k <= n
//ll ans;
char matrix[10][10], available[10][10], colmark[10];
void dfs(int row, int rest)
{
//printf("row = %d rest = %d\n", row, rest);
if(rest == 0)
{
ans++;
return;
}
if(row == n+1)
return;
for(int i = 1;i <= n;i++)
{
if(colmark[i] == 0)
{
//printf("colmark[%d] = %d\n", i, colmark[i]);
//printf("available[%d][%d] = %d\n", i, row, available[i][row]);
if(available[i][row])
{
colmark[i] = 1;
//printf("dfs row = %d rest = %d\n", row+1, rest-1);
dfs(row+1, rest-1);
colmark[i] = 0;
}
}
}
dfs(row+1, rest);
/**加粗部分对应的就是这里!判断不成功也要dfs!只是我们没有放棋子,所以剩余棋子的数量不减少罢了**/
}
//任意的两个棋子不能放在棋盘中的同一行或者同一列
int main()
{
while(scanf("%d %d", &n, &k) && n!=-1 && k!=-1)
{
memset(available, 0, sizeof(available));
for(int i = 1;i <= n;i++)
{
getchar();
for(int j = 1;j <= n;j++)
{
scanf("%c", &matrix[i][j]);
if(matrix[i][j] == '#')
available[i][j] = 1;
}
}
ans = 0;
memset(colmark, 0, sizeof(colmark));
dfs(1, k);
printf("%d\n", ans);
}
return 0;
}
最开始忘记memset available了……WA了,以为是ans的问题(2^31 略略超过10^9),不过后来又试了试用int也可以过。
抄在小本本上:
- 231 int合法