Sweety

Practice makes perfect

导航

棋盘问题

Posted on 2015-02-06 15:42  蓝空  阅读(134)  评论(0编辑  收藏  举报

题目网址:http://acm.pku.edu.cn/JudgeOnline/problem?id=1321

其实就是个神搜的题目,以前做过,但是在拿到题的时候还是会感觉有点我从下手,所以还是多做点就好了吧

具体思路:
棋盘问题, 棋子摆放的位置只能是#, 且不能同行和同列. 由于我采用的是按行递增的顺序来搜索的, 因此不可能出现同行的情况, 对于同列的情况, 我设置了一个变量col[], 来保存列的访问状态, 对于之前访问过的列, 棋子是不能再放在这一列上的.
dfs(begin, num) 代表将第k-num棵棋子放在begin行上, 然后就剩下num-1棵棋子需要放在begin行下面. 当然, 可能存在第num棵棋子根本无法放在begin行上的情况, 对于这种情况, dfs就回溯到上一个dfs调用的地方, 重新开始, 而如果遇到num=1, 且第begin行的一些列可以放的话, 就将方案数相应增加.

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
char ch[10][10];

int visit[10],sum,n;//visit为列的访问状态
void dfs(int begin,int x)
{
    for(int j=0;j<n;j++)
        if(ch[begin][j]=='#'&&visit[j]==0)
            if(x==1)
                sum++;
            else
            {
                visit[j]=1;
                for(int w=begin+1;w<=n-(x-1);w++){//条件w<n-(n-1),这是因为如果在比这个大了就一定不成立了,因为之后一行之多一个,从该地址遍历到结束也不会满足x个了  
                dfs(w,x-1);
                }

                visit[j]=0;
            }
}
int main()
{
    int x; 
    while(~scanf("%d%d",&n,&x)&&!(n==-1&&x==-1))
    {
        sum=0;

        for(int i=0;i<n;i++)
            scanf("%s",ch[i]);
        memset(visit,0,sizeof(visit));
        for(int i=0;i<=n-x;i++) //一共要放x个棋子,每行至多一个,所以需要x行
            dfs(i,x); //从第i行开始,放x个棋子.按照按行递增的顺序访问,一定不会出现同行
        cout<<sum<<endl;
    }
}