1087: [SCOI2005]互不侵犯King
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2182 Solved: 1282
[ Submit][ Status][ Discuss]
Description
在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。
Input
只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N)
Output
方案数。
Sample Input
3 2
Sample Output
16
HINT
Source
ac代码
/**************************************************************
Problem: 1087
User: kxh1995
Language: C++
Result: Accepted
Time:60 ms
Memory:13708 kb
****************************************************************/
#include<stdio.h>
#include<string.h>
long long dp[10][110][1<<10];
int can[1<<10][1<<10],num[1<<10],is[1<<10];
int rt,p;
int n,m;
int count(int x)
{
int c=0;
while(x)
{
c++;
x&=(x-1);
}
return c;
}
void init()
{
int i,j;
p=0;
memset(can,0,sizeof(can));
for(i=0;i<=rt;i++)
{
if(i&(i<<1)||i&(i>>1))
continue;
is[++p]=i;
num[p]=count(i);
for(j=0;j<=rt;j++)
{
if(i&(i<<1)||i&(i>>1))
continue;
if(i&j||i&(j<<1)||j&(i<<1))
continue;
can[i][j]=1;
}
}
}
int main()
{
//int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
rt=(1<<n)-1;
init();
int i,j,k;
for(i=1;i<=p;i++)
{
dp[1][num[i]][is[i]]=1;
}
for(i=1;i<n;i++)
for(j=1;j<=p;j++)
{
for(k=1;k<=p;k++)
{
if(can[is[j]][is[k]])
{
for(int x=num[j];x+num[k]<=m;x++)
{
dp[i+1][x+num[k]][is[k]]+=dp[i][x][is[j]];
}
}
}
}
long long ans=0;
for(i=1;i<=p;i++)
{
ans+=dp[n][m][is[i]];
}
printf("%lld\n",ans);
}
}