1087: [SCOI2005]互不侵犯King
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2274 Solved: 1333
[ 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
解题思路:
状态压缩DP
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,k;
long long f[11][90][600];
int wei[11];
int zan[11];
int i,j,g,h,y;
int main()
{
scanf("%d %d",&n,&k);
memset(f,0,sizeof(f));
f[0][0][0]=1;
int sss=(1<<n)-1;
for (i=1;i<=n;++i)
for (j=0;j<=k;++j)
for (g=0;g<=sss;++g)
{
int u=g; int sug=0; memset(wei,0,sizeof(wei));
bool mm=true;
int ji=1;
while (u>0)
{
if (u%2==1) {++sug;wei[ji]=1;if (wei[ji-1]==1) mm=false;}
++ji;
u=u/2;
}
if (mm==false) continue;
if (sug+j>k){continue;}
for (h=0;h<=sss;++h)
if (f[i-1][j][h]>0)
{
memset(zan,0,sizeof(zan));
u=h; ji=1;
while (u>0)
{
if (u%2==1) {zan[ji]=1;}
++ji;
u=u/2;
}
bool m=true;
for (y=1;y<=n;++y)
if (zan[y]==1)
{
if (y-1>=0 && wei[y-1]==1) m=false;else
if (y+1<=n && wei[y+1]==1) m=false;else
if (wei[y]==1) m=false;
if (m==false) break;
}
if (m==true)
{
f[i][j+sug][g]=f[i][j+sug][g]+f[i-1][j][h];
}
}
}
long long sum=0;
for (int i=0;i<=sss;++i)
if (f[n][k][i]>0)
{
sum+=f[n][k][i];
}
cout<<sum;
}
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,k;
long long f[11][90][600];
int wei[11];
int zan[11];
int i,j,g,h,y;
int main()
{
scanf("%d %d",&n,&k);
memset(f,0,sizeof(f));
f[0][0][0]=1;
int sss=(1<<n)-1;
for (i=1;i<=n;++i)
for (j=0;j<=k;++j)
for (g=0;g<=sss;++g)
{
int u=g; int sug=0; memset(wei,0,sizeof(wei));
bool mm=true;
int ji=1;
while (u>0)
{
if (u%2==1) {++sug;wei[ji]=1;if (wei[ji-1]==1) mm=false;}
++ji;
u=u/2;
}
if (mm==false) continue;
if (sug+j>k){continue;}
for (h=0;h<=sss;++h)
if (f[i-1][j][h]>0)
{
memset(zan,0,sizeof(zan));
u=h; ji=1;
while (u>0)
{
if (u%2==1) {zan[ji]=1;}
++ji;
u=u/2;
}
bool m=true;
for (y=1;y<=n;++y)
if (zan[y]==1)
{
if (y-1>=0 && wei[y-1]==1) m=false;else
if (y+1<=n && wei[y+1]==1) m=false;else
if (wei[y]==1) m=false;
if (m==false) break;
}
if (m==true)
{
f[i][j+sug][g]=f[i][j+sug][g]+f[i-1][j][h];
}
}
}
long long sum=0;
for (int i=0;i<=sss;++i)
if (f[n][k][i]>0)
{
sum+=f[n][k][i];
}
cout<<sum;
}