做过的题,但是忘了怎么做,于是当时用的搜索,搜了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;
}