2018.09.21 codeforces1051D. Bicolorings(线性dp)

传送门
sb线性DP。
f [ i ] [ j ] [ 0 / 1 / 2 / 3 ] f[i][j][0/1/2/3] f[i][j][0/1/2/3]表示前i列j个连通块且第i列状态为00/01/10/11时的方案总数。
这个显然可以轻松转移。
举例:
f [ i ] [ j ] [ 0 ] = ( f [ i − 1 ] [ j ] [ 0 ] + f [ i − 1 ] [ j ] [ 1 ] + f [ i − 1 ] [ j ] [ 2 ] + f [ i − 1 ] [ j − 1 ] [ 3 ] ) f[i][j][0]=(f[i-1][j][0]+f[i-1][j][1]+f[i-1][j][2]+f[i-1][j-1][3])%mod; f[i][j][0]=(f[i1][j][0]+f[i1][j][1]+f[i1][j][2]+f[i1][j1][3])
其它几个同理。
代码:

#include
#define mod 998244353
#define ll long long
#define N 1005
using namespace std;
inline long long read(){
	long long ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
int n,k;
ll f[N][N*2][4];
int main(){
	cin>>n>>k;
	f[1][1][0]=1;
	f[1][1][3]=1;
	f[1][2][1]=1;
	f[1][2][2]=1;
	for(int i=2;i<=n;++i){
		int up=min(i*2,k);
		for(int j=1;j<=up;++j){
			f[i][j][0]=(f[i-1][j][0]+f[i-1][j][1]+f[i-1][j][2]+f[i-1][j-1][3])%mod;
			f[i][j][1]=(f[i-1][j-1][0]+f[i-1][j][1]+f[i-1][j-1][3])%mod;
			if(j>=2)(f[i][j][1]+=f[i-1][j-2][2])%=mod;
			f[i][j][2]=(f[i-1][j-1][0]+f[i-1][j][2]+f[i-1][j-1][3])%mod;
			if(j>=2)(f[i][j][2]+=f[i-1][j-2][1])%=mod;
			f[i][j][3]=(f[i-1][j-1][0]+f[i-1][j][1]+f[i-1][j][2]+f[i-1][j][3])%mod;
		}
	}
	cout<<(f[n][k][0]+f[n][k][1]+f[n][k][2]+f[n][k][3])%mod;
	return 0;
}

你可能感兴趣的:(#,dp,#,基础dp,dp专题)