题意:给定一个正方形棋盘大小,’#’表示这里可以放点,’.’表示为空白区域,再给你一个放点的个数,规则是每放一个点,这个点同行同列的线上都不能有点。问你一共可以有多少种满足情形。
典型的搜索,每行开始扫找到,,每找到一个’#’就放点,改变地图的情形,当找到点与放点个数相等,就算一种。然后再退回去,(回溯?)再 找其他满足题意的情形。
这里 用了两个结构体保存搜索这个点之前和之后的地图情形,所以每次搜索完,就不用 手动还原搜索之前地图的情形。(这个点我还想了很久)
用结构体存存每一次确定放点后,变换后的地图情形。
#include<cstdio>
#include<algorithm>
struct Map
{
char a[10][10];
int x;
};
int n,k;
long long sum;
void dfs(Map tmp,int step)
{
if(step==k+1)
{
sum++;
return;
}
else
{
for(int i=tmp.x+1;i<n+step-k;i++)//由从上个棋子的下一行开始搜,如果剩余可放棋子数明显大于剩余行数,
{ //则可以知道此时无解k-step<=n-i,减去了一点多余时间,用n也能过
for(int j=0;j<n;j++)
{
if(tmp.a[i][j]=='#')
{
Map tmp2;
tmp2=tmp;
tmp2.x=i;
for(int k=i+1;k<n;k++)
{
tmp2.a[k][j]='.';
}
dfs(tmp2,step+1);
}
}
}
}
}
int main()
{
while(scanf("%d %d",&n,&k)&&(n!=-1)&&(k!=-1))
{
sum=0;
Map map;
map.x=-1;
for(int i=0;i<n;i++)
{
scanf("%s",map.a[i]);
}
dfs(map,1);
printf("%lld\n",sum);
}
return 0;
}