题目链接:http://poj.org/problem?id=1321
题意:略。
方法:写在代码中。
不知道是以前打的深搜题太水还是怎么的。。
打起这个来特别费劲,花了1天。各种乱套。。。
写深搜重要3点
1.结束条件
2.标记
3.合理递归
。。。。。。。这道题,写着写着,标记用的数组都省了,- -!!!
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
struct node
{
int y,x;
}kb[80]; //储存“#”所用的数组;
char map[10][10];
int n,k,cnt,js;
long long ans;
bool check(int y,int x) //检查函数,检查“#”里是否可以放棋子;
{
int flag=0;
for(int i=1;i<=n;++i) //检查橫行是否有放过棋子;
if(map[y][i]=='A') //'A'表示棋子;
flag++;
for(int j=1;j<=n;++j) //检查纵列是否有放过棋子;
if(map[j][x]=='A')
flag++;
if(flag>0) //放过棋子返回false;
return false;
return true; //否则返回true;
}
void dfs(int y,int x,int hcnt)
{
if(js==k-1) //判断放下一个棋子时,是否可以符合题意条件;
{
if(check(y,x))
ans++; //可以的话,方案数+1;
return ; //无论可以不可以,直接返回,检查下一个可能放旗子的地方 ;
}
if(!check(y,x)) //如果当前位置无法放置棋子,直接返回,检查下一个可能放旗子的地方;
return ;
else //当前位置可以放置棋子;
{
map[y][x]='A'; //将当前位置置为'A';
js++;
for(int i=hcnt+1;i<cnt;++i) //循环搜寻下一个可能放置的位置;
dfs(kb[i].y,kb[i].x,i); //记得第三个参数为i;
map[y][x]='#'; //回溯部分,将放置过棋子的位置(map[y][x]=='A'),改为空棋盘 ;
js--; //放下棋子个数减1;
}
}
int main()
{
while(cin>>n>>k&&(n!=-1&&k!=-1))
{
cnt=0; //数组下标
ans=0; //最终的方案数目;
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
{
cin>>map[i][j];
if(map[i][j]=='#')
{
kb[cnt].x=j;
kb[cnt++].y=i; //用数组储存含有“#”的点,顺便得到个数。
}
}
for(int i=0;i<cnt;++i)
{
js=0; //记录放下棋子的个数
dfs(kb[i].y,kb[i].x,i); //从第一个“#”开始进行遍历。(重点)第三个参数i代表从i以后的“#”开始遍历 ,防止重复遍历。
map[kb[i].y][kb[i].x]='.'; //遍历过的“#”删除掉,防止重复遍历
}
cout<<ans<<endl;
}
}