题目意思
给你一个n*n的棋盘,让你往上边放k颗棋子,要求每一行或者每一列只能有一颗棋子出现,问你最多有几种方法放置棋子。其中#代表棋盘区域。
解题思路
这道题类似于n皇后问题,主要思想就是深搜加回溯。要找到#,你可以放置棋子也可以不放棋子,但是要求的每行每列都只能有一个棋子,如果放置棋子,就要回溯到原点接着搜索,如果搜到了最后也要回溯,具体看代码
代码部分
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int n,k,ans;
char mp[10][10];
bool judge(int x,int y)
{
for(int i=x-1; i>=0; i--) ///判断同一列有没有放过
{
if(mp[i][y]=='*')
return false;
}
for(int j=y-1; j>=0; j--) ///判断同一行有没有放过
{
if(mp[x][j]=='*')
return false;
}
return true;
}
void dfs(int cur,int s)///cur 为当前点,s为放置了多少个棋子
{
if(s==k)///当达到要求的时候就停止
{
ans++;
return ;
}
if(cur==n*n)///当走到头的时候停止
{
return ;
}
int i=cur/n; //得出来的i,j为当前cur的坐标
int j=cur%n;
if(mp[i][j]=='#'&&judge(i,j))//只有当前点可以放置棋子并且同行同列没有棋子的时候,才可以选择是否在这个地方放置棋子
{
mp[i][j]='*';
dfs(cur+1,s+1);//放置棋子
mp[i][j]='#';
}
dfs(cur+1,s);//不放棋子
}
int main()
{
while(cin>>n>>k)
{
ans=0;
if(n==-1&&k==-1)
break;
for(int i=0; i<n; i++)
scanf(" %s",mp[i]);//在%s之前加空格可以防止数组读取回车
dfs(0,0);
cout<<ans<<endl;
}
}