棋盘问题

棋盘问题 poj1321

    题目大意:给你一个n*n的棋盘,上面有一些格子可以下棋。求在这个棋盘上放置满足条件者的方案数。放在上面的k个棋子,满足任意两个棋子,既不同行,也不同列。

    注释:1<=k<=n<=8.

      想法:啊哈哈!!poj上的中文题,怎么能不A掉呢?但是我开始的想法比较的偏见,在这里说一下,已做纪念。我开始想的是,当每一行都有空格的时候,我期望求出填入n个棋子的方案数,然后乘上组合数$C_{n}^{k}$。然后,必然是wa的。因为有这样一组反例.

        2 1

        #.

        #.

      如果按照我的方法这种情况的方案数就是0,但是我们显然可以找到两种。就是说不能对于任意一种情况都可以完整地填入n个棋子,这组反例是看了Discuss然后发现的。所以,发现了这组反例之后,我决定... ...不再任何剪枝,直接爆搜!其实我们可以发现这题和n皇后差不多,建议A掉了n皇后再做这道题。注意这道题没有限制斜边的情况,所以不用像n皇后一样弄3个bool数组来判定情况。

    最后,附上丑陋的代码... ...

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 int ans;
 6 bool v[10];
 7 char s[10][10];
 8 int before[10];
 9 int n,k,all;
10 void dfs(int x)
11 {
12     if(all==k)
13     {
14         ans++;
15         return;
16     }
17     if(x==n+1)
18     {
19         return;
20     }
21     for(int i=1;i<=n;i++)
22     {
23         if(s[x][i]=='#'&&!v[i])
24         {
25             v[i]=1;
26             all++;
27             dfs(x+1);
28             v[i]=0;
29             all--;
30         }
31     }
32     dfs(x+1);
33 }
34 int main()
35 {
36     while(~scanf("%d%d",&n,&k))
37     {
38         all=0;
39         ans=0;
40         if(n==-1&&k==-1) return 0;
41         memset(v,false,sizeof(v));
42         memset(s,0,sizeof(s));
43         for(int i=1;i<=n;i++)
44         {
45             scanf("%s",s[i]+1);
46         }
47         dfs(1);
48         printf("%d\n",ans);
49     }
50 }

    小结:当你想到了一个比较强的结论的时候,记得不要直接码,先看一看可不可以直接用一组比较简单的情况卡掉。一般情况下,一些比较优秀的算法在小数据是不怎么太实用的。如果一个c++算法在小数据是错误的,这个算法就可以通过等量的放大,就可以将这个算法D掉。

posted @ 2018-02-07 22:36  JZYshuraK_彧  阅读(210)  评论(0编辑  收藏  举报