【状态压缩DP】互不侵犯

来源:互联网 发布:淘宝充流量一直不到账 编辑:程序博客网 时间:2024/04/30 18:43

做过的题,但是忘了怎么做,于是当时用的搜索,搜了60分。


三、互不侵犯(King)

     在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。

 

输入文件:

只有一行,包含两个数N,K ( 1 <=N <=9,  0 <= K <= N * N)

输出文件:

      方案数。

 

Sample Input

3 2

 

Sample Output

16


其实这道题不用那么麻烦,稍微牺牲一点时间,每一次对上一排都遍历所有可能的方法,而不用只枚举生成了的状态,实践证明,已经够快了。。而且这样来思维难度降低了很多


提交次数:3

1、TLE60。朴素

2、WA80。没有用long long

3、AC


#include <cstdio>#include <string>#include <cstring>long getint(){long rs=0;char tmp;bool sgn=0;do tmp = getchar();while (!isdigit(tmp)&&tmp-'-');if (tmp=='-'){tmp=getchar();sgn=1;}do rs=(rs<<3)+(rs<<1)+tmp-'0';while (isdigit(tmp=getchar()));return sgn?-rs:rs;}long n,K;long met[4000];long cnt[4000];long long f[10][4000][200];long mc = 0;void make(long l,long s,long c){if (l == n+1){++mc;met[mc] = s;cnt[mc] = c;return;}make(l+1,s,c);if (!(s&(1<<(l-1))))make(l+1,s|(1<<l),c+1);}int main(){freopen("king.in","r",stdin);freopen("king.out","w",stdout);n = getint();K = getint();make(1,0,0);for (long i=1;i<mc+1;i++){f[1][i][cnt[i]] = 1;}for (long i=2;i<n+1;i++){for (long j=1;j<mc+1;j++){for (long k=1;k<mc+1;k++){for (long c=cnt[k];c<K+1;c++){if (!(met[k]&met[j])&&!((met[k]>>1)&met[j])&&!((met[k]<<1)&met[j]))f[i][k][c] += f[i-1][j][c-cnt[k]];}}}}long long ans = 0;for (long i=1;i<mc+1;i++){ans += f[n][i][K];}printf("%I64d",ans);return 0;}