P1896 [SCOI2005]互不侵犯
题目描述
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。
注:数据有加强(2018/4/25)
输入输出格式
输入格式:
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
输出格式:
所得的方案数
输入输出样例
3 2
16
#include <bits/stdc++.h>
using namespace std;
long long dp[10][1<<9][82]; //第i行j状态下放了k个国王的最大方案数
int c[1<<9];//记录一行中每种状态下的国王数量
void init()
{
for(int i=0;i<(1<<9);i++)
{
int k=i;
for(int j=0;j<9;j++)
{
c[k]+=(i>>j&1);
}
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
init();
long long ans=0;
dp[0][0][0]=1;
for(int k=1;k<=m;k++)
{
for(int i=1; i<=n; i++)
{
for(int S=0; S<(1<<n); S++)
{
if(S&(S<<1)) continue; //国王相邻,continue;
if(k-c[S]<0) continue; //国王超过k,continue;
for(int s=0; s<(1<<n); s++)
{
if((S&s)||((S>>1)&s)||((S<<1)&s)) continue; //判断与上一行的状态
dp[i][S][k]+=dp[i-1][s][k-c[S]];
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=0;j<(1<<n);j++)
ans+=dp[i][j][m];
}
}
printf("%lld\n",ans);
return 0;
}
扫描二维码关注公众号,回复:
2659005 查看本文章