在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案。国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子。
3 2
16
1 ≤ N ≤ 9 , 0 ≤ K ≤ N 2 1 \leq N \leq 9, 0 \leq K \leq N^2 1≤N≤9,0≤K≤N2
我们可以设 f ( i , j , k ) f(i,j,k) f(i,j,k)
那么显然我们的状态转移方程为
f [ i ] [ 1 ] [ k ] = f [ i − 1 ] [ 0 ] [ k ] f[i][1][k]=f[i-1][0][k] f[i][1][k]=f[i−1][0][k]
f [ i ] [ 0 ] [ k ] = f [ i − 1 ] [ 1 ] [ k ] f[i][0][k]=f[i-1][1][k] f[i][0][k]=f[i−1][1][k]
边界条件为 f [ 1 ] [ 1 ] [ 1 ] = f [ 1 ] [ 0 ] [ 0 ] = 1 f[1][1][1]=f[1][0][0]=1 f[1][1][1]=f[1][0][0]=1
最后统计 a n s = f [ n ] [ 1 ] [ K ] + f [ n ] [ 0 ] [ K ] = 2 ( → _ → ) ans=f[n][1][K]+f[n][0][K]=2 (→\_→) ans=f[n][1][K]+f[n][0][K]=2(→_→)
我们需要设 f ( i , j 1 , j 2 , k ) f(i,j_1,j_2,k) f(i,j1,j2,k)
状态转移方程这里就不在累述,显而易见,我们的状态表示数组变成了四维的,推而广之
有几列,需要n+2维的数组来维护。
然而最多可以有9列,所以,如果按照一般的做法,应该开一个十二维的数组来维护。也就是需要
9 × 9 9 × 81 = 282429536481 ∗ 4 字 节 ≈ 1 T B 9\times9^9\times81=282429536481*4字节\approx1TB 9×99×81=282429536481∗4字节≈1TB的内存。
所以我们需要一个更加优秀的方法来维护。
通过观察,我们发现对于 f ( i , j 1 , j 2 , j 3 , ⋯   , j n , k ) f(i,j_1,j_2,j_3,\cdots,j_n,k) f(i,j1,j2,j3,⋯,jn,k)来说, j 1 , j 2 , j 3 , ⋯   , j n j_1,j_2,j_3,\cdots,j_n j1,j2,j3,⋯,jn都是1或0,所以,我们可以很自然地想到二进制。
于是,正解就这么被想到了:用一个二进制数来表示 j 1 , j 2 , j 3 , ⋯   , j n j_1,j_2,j_3,\cdots,j_n j1,j2,j3,⋯,jn,于是,一个最多十二维的数组,被我们压缩成了一个三维的数组
f ( i , j , k ) f(i,j,k) f(i,j,k)
但是到这里我们去dp还是不方便,所以,我们需要先dfs预处理出所有的可能,然后再去dp
void dfs(int tot,int sum,int tag)
{
if(tag>=n)//找完了
{
sit[++cnt]=tot;
gs[cnt]=sum;
return ;//这里需要结束
}
dfs(tot,sum,tag+1);//因为这里不用第tag个,所以tag+1
dfs(tot+(1<<tag),sum+1,tag+2);//这里要用第tag个,所以需要tag+2
}
那么我们的状态转移方程就是
f [ i ] [ j ] [ s ] + = f [ i − 1 ] [ k ] [ s − g s [ j ] ] f[i][j][s]+=f[i-1][k][s-gs[j]] f[i][j][s]+=f[i−1][k][s−gs[j]]
最后统计
a n s + = f [ N ] [ i ] [ K ] ans+=f[N][i][K] ans+=f[N][i][K]
#include
#define ll long long
using namespace std;
ll f[10][2000][520];
inline ll read()
{
ll f=1,k=0;
char c=getchar();
while(c>'9'||c<'0')
{
if(c=='-')f=-1;
c=getchar();
}
while(c>='0'&&c<='9')k=(k<<1)+(k<<3)+(c^48),c=getchar();
return f*k;
}
ll n,m,cnt;
ll sit[2333],gs[2333];
void dfs(int tot,int sum,int tag)
{
if(tag>=n)
{
sit[++cnt]=tot;
gs[cnt]=sum;
return ;
}
dfs(tot,sum,tag+1);
dfs(tot+(1<<tag),sum+1,tag+2);
}
int main()
{
n=read();m=read();
dfs(0,0,0);
for(int i=1;i<=cnt;i++)f[1][i][gs[i]]=1;
for(int i=2;i<=n;i++)
for(int j=1;j<=cnt;j++)
for(int k=1;k<=cnt;k++)
{
if(sit[j]&sit[k])continue;
if(sit[j]&(sit[k]<<1))continue;
if((sit[j]<<1)&sit[k])continue;
for(int s=m;s>=gs[j];s--)f[i][j][s]+=f[i-1][k][s-gs[j]];
}
ll ans=0;
for(int i=1;i<=cnt;i++)ans+=f[n][i][m];
printf("%lld",ans);
return 0;
}
❀完结撒花❀
❀ ❀
❀ ❀