专栏文章

题解:CF1051D Bicolorings

CF1051D题解参与者 2已保存评论 1

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@mipzcwcn
此快照首次捕获于
2025/12/03 20:25
3 个月前
此快照最后确认于
2025/12/03 20:25
3 个月前
查看原文
动态规划,很有思维含量。
首先看到题还以为打表找规律,但是规律好像是没有的。
注意到棋盘宽为二,那每次往右边摆两个就有四种方式:黑黑,黑白,白黑,白白。那就可以将 dpi,j,kdp_{i,j,k} 表示为前 ii 列有 jj 个连通块时当前为第 kk 种摆法的方案数。
初始化:
CPP
dp[1][1][1]=1;
dp[1][2][2]=1;
dp[1][2][3]=1;
dp[1][1][4]=1;
转移方式推的时候可以画图便于推式:
CPP
//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];
答案就是将所有最后列都加起来。

代码

CPP
#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;
}

评论

1 条评论,欢迎与作者交流。

正在加载评论...