P1896
[SCOI2005] 互不侵犯
题目描述
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。
注:数据有加强(2018/4/25)
输入格式
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
输出格式
所得的方案数
样例 #1
样例输入 #1
3 2
样例输出 #1
16
woc
我第一次纯自己写状压一遍写对!
状压注意细节!!!
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int k,n;
int f[10][85][(1<<10)];
signed main()
{
ios::sync_with_stdio(false);
cin>>n>>k;
for(int t=0;t<(1<<n);t++)
{
int flag=1;
for(int l=0;l<n;l++)
if((t&(1<<l))&&(t&(1<<(l+1))))
{
flag=0;
break;
}
if(!flag)continue;
int cnt=0;
for(int l=0;l<n;l++)
if(t&(1<<l))
cnt++;
f[1][cnt][t]=1;
}
int cnt1,cnt2;
for(int i=2;i<=n;i++)
{
for(int j=0;j<=k;j++)
{
for(int t=0;t<(1<<n);t++)
{
cnt1=0;cnt2=0;
for(int p=0;p<n;p++)
if(t&(1<<p))cnt1++;
int flag=1;
for(int p=0;p<n;p++)
if((t&(1<<p))&&(t&(1<<(p+1))))
{
flag=0;
break;
}
if(!flag)continue;
for(int l=0;l<(1<<n);l++)
{
int pd=1;
for(int p=0;p<n;p++)
{
if((l&(1<<p))&&(t&(1<<p))){pd=0;break;}
if((l&(1<<p))&&(t&(1<<(p+1)))){pd=0;break;}
if((l&(1<<p))&&(t&(1<<(p-1)))){pd=0;break;}
}
if(!pd)continue;
for(int p=0;p<n;p++)
if(l&(1<<p))cnt2++;
if(j-cnt1>=0)
f[i][j][t]+=f[i-1][j-cnt1][l];
}
}
}
}
int tot=0;
for(int t=0;t<(1<<n);t++)
{
int cnt=0;
for(int p=0;p<n;p++)
if(t&(1<<p))cnt++;
if(k>=cnt)
tot+=f[n][k][t];
}
cout<<tot<<"\n";
return 0;
}
此生无悔入OI 来生AK IOI

浙公网安备 33010602011771号