题解:CF1051D Bicolorings
Pyrf_uqcat · · 题解
动态规划,很有思维含量。
首先看到题还以为打表找规律,但是规律好像是没有的。
注意到棋盘宽为二,那每次往右边摆两个就有四种方式:黑黑,黑白,白黑,白白。那就可以将
初始化:
dp[1][1][1]=1;
dp[1][2][2]=1;
dp[1][2][3]=1;
dp[1][1][4]=1;
转移方式推的时候可以画图便于推式:
//1:X 2:X 3:. 4:.
//X . X .
dp[i][j][1]+=dp[i-1][j][1]+dp[i-1][j][2]+dp[i-1][j][3]+dp[i-1][j-1][4];
dp[i][j][2]+=dp[i-1][j-1][1]+dp[i-1][j][2]+dp[i-1][j-2][3]+dp[i-1][j-1][4];
dp[i][j][3]+=dp[i-1][j-1][1]+dp[i-1][j-2][2]+dp[i-1][j][3]+dp[i-1][j-1][4];
dp[i][j][4]+=dp[i-1][j-1][1]+dp[i-1][j][2]+dp[i-1][j][3]+dp[i-1][j][4];
答案就是将所有最后列都加起来。
代码
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e3+5;
const int mod=998244353;
int n,k;
int dp[N][2*N][5];
inline void init()
{
dp[1][1][1]=1;
dp[1][2][2]=1;
dp[1][2][3]=1;
dp[1][1][4]=1;
}
signed main()
{
cin>>n>>k;
init();
for(int i=2;i<=n;i++)
{
for(int j=1;j<=k;j++)
{
// 1:X 2:X 3:. 4:.
// X . X .
dp[i][j][1]+=dp[i-1][j][1]+dp[i-1][j][2]+dp[i-1][j][3]+dp[i-1][j-1][4];
dp[i][j][2]+=dp[i-1][j-1][1]+dp[i-1][j][2]+dp[i-1][j-2][3]+dp[i-1][j-1][4];
dp[i][j][3]+=dp[i-1][j-1][1]+dp[i-1][j-2][2]+dp[i-1][j][3]+dp[i-1][j-1][4];
dp[i][j][4]+=dp[i-1][j-1][1]+dp[i-1][j][2]+dp[i-1][j][3]+dp[i-1][j][4];
dp[i][j][1]%=mod,dp[i][j][2]%=mod,dp[i][j][3]%=mod,dp[i][j][4]%=mod;
// cout<<i<<' '<<j<<' '<<dp[i][j][1]<<' '<<dp[i][j][2]<<' '<<dp[i][j][3]<<' '<<dp[i][j][4]<<endl;
}
}
int ans=0;
for(int i=1;i<=4;i++)
{
ans+=dp[n][k][i];
ans%=mod;
}
cout<<ans<<endl;
return 0;
}