状压dp 涂抹果酱 求调
  • 板块学术版
  • 楼主Q__A__Q
  • 当前回复0
  • 已保存回复0
  • 发布时间2022/10/22 23:25
  • 上次更新2023/10/27 06:23:51
查看原帖
状压dp 涂抹果酱 求调
372172
Q__A__Q楼主2022/10/22 23:25

涂抹果酱

【题目描述】

Tyvj 两周年庆典要到了,Sam 想为 Tyvj 做一个大蛋糕。蛋糕俯视图是一个 N×M 的 矩形,它被划分成 N×M 个边长为 1×1 的小正方形区域(可以把蛋糕当成 N 行 M 列的 矩阵)。蛋糕很快做好了,但光秃秃的蛋糕肯定不好看!所以,Sam 要在蛋糕的上表面涂抹 果酱。果酱有三种,分别是红果酱、绿果酱、蓝果酱,三种果酱的编号分别为 1,2,3。为了 保证蛋糕的视觉效果,Admin 下达了死命令:相邻的区域严禁使用同种果酱。但 Sam 在接 到这条命令之前,已经涂好了蛋糕第 K 行的果酱,且无法修改。

现在 Sam 想知道:能令 Admin 满意的涂果酱方案有 多少种。请输出方案数 mod 106。

若不存在满足条件的方案,请输出 0。

【输入】

输入共三行。

第一行:N,M;

第二行:K;

第三行:M 个整数,表示第 K 行的方案。

字母的详细含义见题目描述,其他参见样例。

【输出】

输出仅一行,为可行的方案总数。

【输入输出样例】

输入

2 2

1

2 3

输出

3

【样例说明】

方案一 方案二 方案三

2 3 2 3 2 3 1 2 3 1 3 2

【数据范围】

对于 30% 的数据,1≤N×M≤20;

对于 60% 的数据,1≤N≤1000,1≤M≤3;

对于 100% 的数据,1≤N≤10000,1≤M≤5。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;

const int maxn=1e4+10;
const int inf=1e6;
int n,m,k,ans,f,dp[maxn][500],ok[3000],c[3000];
int p[]= {1,3,9,27,81,243,729,729*3};

inline int read() {
	int s=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9') {
		if(ch=='-')w=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
	return s*w;
}

inline void write(int x) {
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);
	putchar(x%10+'0');
}

inline bool chk(int x) {
	int tmp=-1;
	for(int i=1; i<=m; i++) {
		if(tmp==x%3)return 0;
		tmp=x%3,x/=3;
	}
	return 1;
}

inline bool checkk(int x,int y) {
	for(int i=1; i<=m; ++i) {
		if(x%3==y%3) return 0;
		x/=3,y/=3;
	}
	return true;
}

signed main() {
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	n=read(),m=read(),k=read();
	for(int i=1; i<=m; ++i) {
		c[i]=read();
//		if(c[i]==3) f*=3;
		f=f*3+c[i]-1;
	}
	int num=0;//num1=0;
	for(int i=0; i<p[m]; ++i) {
		if(chk(i)) ok[++num]=i;
//		if(checkk(i,i*3)&&checkk(i,i/3)) kk[++num1]=i;
	}
//	for(int i=1;i<=num;++i)
//		cout<<ok[i]<<' '<<kk[i]<<endl;
//	for(int i=1;i<=p[m];++i) {
//		puts("");
//		for(int j=1;j<=p[m];++j)
//			cout<<checkk(i,j)<<' ';
//	}
	if(k!=1)
		for(int i=1; i<=num; ++i)
			dp[1][ok[i]]=1;
	for(int i=1; i<=n; ++i) {
//		if(i==1) continue;
		if(i==k) {
			if(k==1)
				dp[k][f]=1;
			else
				for(int j=1; j<=num; ++j) {
					int s1=ok[j];
					if(checkk(f,s1))
						dp[k][f]=(dp[k][f]+dp[k-1][s1])%inf;
				}
		}
		else for(int j=1; j<=num; ++j) {
			int s=ok[j];
			for(int h=1; h<=num; ++h) {
				if(checkk(ok[h],s))
					dp[i][j]=(dp[i][j]+dp[i-1][ok[h]])%inf;
			}
		}
	}
	for(int i=1; i<=num; ++i)
		ans=(ans+dp[n][ok[i]])%inf;
	write(ans);
	return 0;
}

2022/10/22 23:25
加载中...