1087: [SCOI2005]互不侵犯King
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 5850 Solved: 3433
Description
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上
左下右上右下八个方向上附近的各一个格子,共8个格子。
Input
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
Output
方案数。
Sample Input
3 2
Sample Output
16
解析:
状压DP。
代码:
#include <bits/stdc++.h>
using namespace std;
const int Max=520;
int n,m;
long long f[10][85][Max],ans;
int g[Max];
inline int get_int()
{
int x=0,f=1;
char c;
for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
if(c=='-') f=-1,c=getchar();
for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
return x*f;
}
int main()
{
n=get_int(),m=get_int();
if(m>n*n) {cout<<"0\n";return 0;}
f[0][0][0]=1;
for(int i=1;i<(1<<n);i++) g[i]=g[i>>1]+(1&i);
for(int i=1;i<=n;i++)
for(int j=0;j<(1<<n);j++)
if(g[j]<=m && !(j&(j<<1)))
for(int k=0;k<(1<<n);k++)
if(g[k]<=m && !(k&(k<<1)) && !(j&k) && !(j&(k<<1)) &&!(j&(k>>1)))
for(int s=g[j]+g[k];s<=m;s++)
f[i][s][j]+=f[i-1][s-g[j]][k];
for(int i=0;i<=(1<<n);i++) ans+=f[n][m][i];
cout<<ans<<"\n";
return 0;
}