状压DP【洛谷P1896】 [SCOI2005]互不侵犯
P1896 [SCOI2005]互不侵犯
题目描述
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。
注:数据有加强(2018/4/25)
输入输出格式
输入格式:
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
输出格式:
所得的方案数
\(continue\)和\(break\)傻傻分不清,也是挺厉害了。。。
code:
#include <iostream>
#include <cstdio>
#define int long long
using namespace std;
inline int read(){
int sum=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0';ch=getchar();}
return sum*f;
}
int n,m,ans;
int f[11][1<<10][101];
signed main(){
n=read();m=read();
int WX=(1<<n);
f[0][0][0]=1;
for(int i=1;i<=n;i++)
{
for(int j=0;j<WX;j++)
{
int flag=0,tot=0;
for(int tmp=1;tmp<=n;tmp++)
{
if(j&(1<<tmp-1))tot++;
if(((j&(1<<tmp-1))&&((j&(1<<tmp)))))
{
flag=1;break;
}
}
if(flag)continue;
if(tot>m)continue;
for(int k=0;k<WX;k++)
{
int flag=0;
for(int tmp=1;tmp<=n;tmp++)
{
if(((k&(1<<tmp-1))&&((k&(1<<tmp)))))
{
flag=1;break;
}
}
if(flag)continue;
for(int tmp=1;tmp<=n;tmp++)
{
if(((k&(1<<tmp-1))&&(j&(1<<tmp)))||((k&(1<<tmp-1))&&(j&(1<<(tmp-1))))||((k&(1<<tmp-1))&&(j&(1<<(tmp-2)))))
{
flag=1;break;
}
}
if(flag)continue;
for(int l=tot;l<=m;l++)
{
f[i][j][l]+=f[i-1][k][l-tot];
}
}
}
}
for(int i=0;i<WX;i++){
ans+=f[n][i][m];
}
printf("%lld\n",ans);
return 0;
}