一个n*n的棋盘里面放k个棋子。有点类似于8皇后问题。只不过是有些地方不能放棋子。并且放棋子数只需要k个就行了。
想到了类似于8皇后问题就采用深搜的方式。
由于只要放k个棋子,且有些行不能放棋子。所以可以先预处理一下,看哪些行需要放棋子。
处理当前行的时候有两种状态,一是在当前航放棋子,二是不放棋子。放棋子就类似于8皇后判断是否有相同列,不放棋子则直接深搜下一行。
再加一些剪枝。当前放了chess_num个棋子,还剩n-cur+1行没有放,如果把剩下的行全放棋子都不可能有k个棋子,则可以剪掉。
AC代码:
#include<iostream>
#include<cstring>
using namespace std;
const int Arsize=9;
int Maps[Arsize][Arsize];
int vis[Arsize];
int have_to_put[Arsize];
int n,k;
int ans,rear;
void dfs(int cur,int chess_num){
int i;
if(chess_num==k){
ans++;
return;
}
if(cur>=n)
return ;
if(chess_num+n-cur<k)
return ;
if(have_to_put[cur]==0)
dfs(cur+1,chess_num);
else{
for(i=0;i<n;i++){
if(Maps[cur][i]&&!vis[i]){
vis[i]=1;
dfs(cur+1,chess_num+1);
vis[i]=0;
}
}
dfs(cur+1,chess_num);
}
}
int main()
{
int i,j,row=0;
char str[10];
while(cin >> n >> k){
cin.get();
if(n==-1&&k==-1)
break;
ans=0;
memset(Maps,0,sizeof(Maps));
memset(vis,0,sizeof(vis));
row=0;
for(i=0;i<Arsize;i++)
have_to_put[i]=-1;
for(i=0;i<n;i++){
cin.getline(str,10);
for(j=0;j<n;j++){
if(str[j]=='.')
Maps[i][j]=0;
else if(str[j]=='#'){
Maps[i][j]=1;
have_to_put[i]=1;
}
}
}
dfs(0,0);
cout << ans << endl;
}
return 0;
}
今儿很高兴啊。
自己终于不用参照解题报告的也能A掉3个题了。
所以说题目越多越有灵感。哈哈!