目录
显示
题目链接
题解
我们设 \(f_{i,j}\) 表示填完 \(i\) 行 \(j\) 列的方案数。
对于当前行,我们有如下四种决策:
- 啥都不放:\(f_{i-1,j}\);
- 放一个帐篷单独占据一列(方向任意):\(4 \times j \times f_{i-1,j-1}\);
- 在同一行放两个帐篷占据两列:\(\frac{j(j-1)}{2} \times f_{i-1}{j-2}\);
- 在同一列放两个帐篷占据两行:\((i-1) \times j \times f_{i-2,j-1}\);
时间复杂度 \(O(HW)\)。
#include <iostream>
#define MOD 1000000007
using namespace std;
long long f[3005][3005];
int main()
{
int h,w;
cin>>h>>w;
for(int i=0;i<=h;i++)
f[i][0]=1;
for(int i=0;i<=w;i++)
f[0][i]=1;
for(int i=1;i<=h;i++)
for(int j=1;j<=w;j++)
{
f[i][j]=f[i-1][j];
f[i][j]=(f[i][j]+4*j*f[i-1][j-1])%MOD;
if(i>=2)
f[i][j]=(f[i][j]+f[i-2][j-1]*j*(i-1))%MOD;
if(j>=2)
f[i][j]=(f[i][j]+f[i-1][j-2]*j*(j-1)/2)%MOD;
}
cout<<(f[h][w]-1+MOD)%MOD<<endl;
return 0;
}