AtCoder Regular Contest 074E RGB Sequence dp

版权声明:转吧转吧这条东西只是来搞笑的。。 https://blog.csdn.net/jpwang8/article/details/89017185

Description


长度为n的序列可以涂RGB三种颜色,m个限制形如l,r,x表示l到r有恰好x种颜色
问满足所有要求的涂色方案数
n 300 n\le300

Solution


一开始想到了一个非常假的做法。。结果当然没过啦

设f[i,a,b,c]表示到了第i个位置,三种颜色最后出现的位置分别是a、b、c的方案数。这个转移非常好想
然后我们可以发现每个位置都要涂色,那么就可以设f[a,b,c]这样了。对于限制我们把限制挂在r上,那么讨论一下三种颜色和l的关系就可以转移了

Code


#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define fi first
#define se second

typedef std:: pair <int,int> pair;
const int MOD=1e9+7;
const int N=305;

int f[N][N][N];

std:: vector <pair> vec[N];

int read() {
	int x=0,v=1; char ch=getchar();
	for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):v,ch=getchar());
	for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
	return x*v;
}

void upd(int &x,int v) {
	x+=v; (x>=MOD)?(x-=MOD):0;
}

int main(void) {
	int n=read(),m=read();
	rep(i,1,m) {
		int l=read(),r=read(),x=read();
		vec[r].push_back(pair(l,x));
	}
	f[1][0][0]=3;
	rep(i,1,n-1) {
		rep(j,0,i) {
			rep(k,0,j) {
				if (!f[i][j][k]) continue;
				for (int t=0;t<vec[i].size();++t) {
					int l=vec[i][t].fi,x=vec[i][t].se;
					if ((x==1)&&(l<=j)) {f[i][j][k]=0; break;}
					if ((x==2)&&(l<=k||l>j)) {f[i][j][k]=0; break;}
					if ((x==3)&&l>k) {f[i][j][k]=0; break;}
				}
				if (!f[i][j][k]) continue;
				upd(f[i+1][j][k],f[i][j][k]);
				upd(f[i+1][i][j],f[i][j][k]);
				upd(f[i+1][i][k],f[i][j][k]);
			}
		}
	}
	int ans=0;
	rep(j,0,n) rep(k,0,j) {
		if (!f[n][j][k]) continue;
		for (int t=0;t<vec[n].size();++t) {
			int l=vec[n][t].fi,x=vec[n][t].se;
			if ((x==1)&&(l<=j)) {f[n][j][k]=0; break;}
			if ((x==2)&&(l<=k||l>j)) {f[n][j][k]=0; break;}
			if ((x==3)&&l>k) {f[n][j][k]=0; break;}
		}
		if (!f[n][j][k]) continue;
		upd(ans,f[n][j][k]);
	}
	printf("%d\n", ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/jpwang8/article/details/89017185