第二天又写了一个下午的搜索题。愚蠢致死。进一步总结思路。
POJ 1321 :http://poj.org/problem?id=1321
正确的题意是: 给你矩阵(方形)的边,给你一个 旗子数 k 。 接下来给出由字符 '.' 和 '#’ 的方形矩阵。 要在 '#' 位置放棋子。 请问有几种合法的放置组合方法。不是排列!!
合法的放置 题目要求为 : 任何两个旗子不可在同一行同一列。
刚开始的时候没想到一点,所有的位置都会放满。殊不知,按照题目, # 的数目可能会比棋子数多,也可能会少。这么显而易见的题意没有在意,导致后来找bug找到死。
看到题目的第一反应就是,此题和八皇后一个套路。当时在搜索的过程中,判断同行列有无旗子都是傻不拉几的 用循环查看。后来的思路改为 抽象为数字。
如八行的矩阵,若表示为 12050000,则表示 在第一行第一列放了一个棋子,第二行第二列放了一个棋子,以及 第四行第五列放了一个棋子。0代表此行无子。
我的第几位,表示第几行,位上的数字表示第几列,因为同列同行尽可能为1子,故同位 只可能有一个数字。 当然如果反过来写也行。
故 用book数组标记各列有无元素出现,有则此列不可添加元素。
用 tag 数组 并用上述的数字方法 来记录各行各列旗子填放情况。
最终代码的DFS 思路:
两个形参:当前填数字的行数,当前已经填放的棋子数。
DFS前预处理,对各行的#号的出现列数用vector保存。
判断是否填完最后一行,是则判断已填棋子数是否达到题目标准,有则添加ans,递归结束
(判断是否到达结束条件)
对当前行,循环填放 vector中的各列 的可能。 若此列尚无元素,就填上,即递归
( 递归的具体实现 )
哎,代码还是要多练啊。
上DFS代码:
#include"cstdio"
#include"vector"
#include"cstring"
using namespace std;
#define loop(x,y,z) for(x=y;x<z;x++)
char pos[10][10];
int book[10];
int n,k,ans,tag[10];
vector<char>v[10];
void dfs(int i,int sum)
{
int j;
if(i==n)
{
if(sum==k)
ans++;
return;
}
int len=v[i].size();
for(j=0;j<len;j++)
{
int x=v[i][j];
if(!book[x])
{ tag[i]=x;
book[x]=1;
dfs(i+1,sum+1);
book[x]=0;
}
}
dfs(i+1,sum);
}
int main()
{
int i,j;
while(~scanf("%d%d",&n,&k))
{
if(n==-1&&k==-1)break;
memset(book,0,sizeof book);
memset(tag,-1,sizeof tag);
loop(i,0,n)
v[i].clear();
ans=0;
loop(i,0,n)
scanf("%s",pos[i]);
loop(i,0,n)
loop(j,0,n)
if(pos[i][j]=='#')
v[i].push_back(j);
dfs(0,0);
printf("%d\n",ans);
}
return 0;
}