2018.4.21 T2

物理题
【问题描述】
物理课上,Enos 正在做电学实验。Enos 有一排灯座,总共可以接 m
个小灯泡。他还有 n 种小灯泡,每种小灯泡标有额定功率 pi,ai ,不同的小
灯泡额定功率不同。为了使接通电源后灯座上的灯泡由暗到亮变化,要求
小灯泡要按额定功率从小到大接。为避免接通电源后发光序列过于单调,
规定不能有超过 ai 只连续的第 i 种小灯泡。不过 Enos 发现,在灯座上已
经固定了一些小灯泡,它们无法被取下来。现在 Enos 想知道,在电源接通
下一共能有多少种不同的发光序列?可以不用某种小灯泡,但总共接入的
小灯泡数必须恰为 m。
【输入格式】
从文件 physics.in 中读入数据。
第一行两个正整数 n,m,分别表示小灯泡的个数和灯座上的接口数。
接下来 n 行,每行两个正整数 pi ,ai ,含义如上描述。
接下来一行个 m 整数 bi ,如果 bi 为 0 表示第 i 个接口没有小灯泡,否
则表示第 i 个接口已经固定有一只第 bi 种的小灯泡。
【输出格式】
输出到文件 physics.out 中。
一行一个整数表示不同的发光序列数。由于答案可能很大,你只需要
输出答案除以 1 000 000 007 的余数即可。如果没有一种可行的方案,输出

一行 −1

----------------------------------------------------------------------

显然是DP,每种灯泡显然连续,方案数%P==0 数据难造没卡你

f[i][j][k]表示第i位,第j种灯泡,长度为k的方案数,转移在代码里

#include <cstdio>
using namespace std;
const int N=105,P=1000000007;
int f[N][N][N];
int pd[N][N][N];
int p[N],a[N]={1},b[N];
int n,m,ans;
int main() {
	freopen("physics.in","r",stdin);
	freopen("physics.out","w",stdout);
	scanf ("%d%d",&n,&m);
	for (int i=1;i<=n;i++)
		scanf ("%d%d",&p[i],&a[i]);
	for (int i=1;i<=m;i++)
		scanf ("%d",&b[i]);
	f[0][0][1]=1;pd[0][0][1]=1;//pd是判-1,转移和f一样,可以不看
	for (int i=1;i<=m;i++) {
		for (int j=1;j<=n;j++){
			if (b[i] && j!=b[i]) continue;//b[i]!=0 ,只需转移b[i]
			for (int k=0;k<=n;k++) {
				if (p[k]>p[j]) continue;
				for (int l=1;l<=a[k];l++){
					if (j==k) f[i][j][l]=(f[i][j][l]+f[i-1][k][l-1])%P;//前后相等长度加1
					else f[i][j][1]=(f[i][j][1]+f[i-1][k][l])%P;//长度为1由其他所有情况转移
					if (j==k) pd[i][j][l]|=pd[i-1][k][l-1];
					else pd[i][j][1]|=pd[i-1][k][l];
				}
			}
		}
	}
	int che=0;
	for (int j=1;j<=n;j++)
		for (int k=1;k<=a[j];k++)  {
			ans=(ans+f[m][j][k])%P;
			if (pd[m][j][k]) che=1;
		}
	if (!che) puts("-1");
	else printf("%d",ans);
}
	

还有二维的

猜你喜欢

转载自blog.csdn.net/qq_41893580/article/details/80033562
T2