51NOD 1636 教育改革 (DP+思维)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/PK__PK/article/details/82971159

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1636

题意:

题解:根据题意,很容易写出DP【i】【j】表示第 i 天,作业量为 j 的最大的总作业量。但是 j 为1e16很大,空间爆炸。所以需要想办法,把每天的作业量表示出来。根据数据可知,每天的作业量的最大值最小值不超过100,根据这个条件。我们显然能推出

DP【i】【j】【L】表示第 i 天选 第 j 门,且差值为L的最大的总作业量。那么我们就可以用 j 和 L表示某天选择 j 门课所获等的作业量为 a【j】 + L 。

那么就可以转移了。

首先 第 i 天 一定是 又 i - 1 天转移回来,只有两种转移方式。最大总作业量 减 k 或 除 k。还要保证 复杂度是严格递增的,所以还需要先按照复杂度 排序。

所以我们需要依次枚举天数 i , 和第 i 天的选择哪门课,还有这门课的差值L,还有 i - 1天的课程。

代码如下:

#include<bits/stdc++.h>
using namespace std;
long long dp[55][55][105];
struct node{
	long long a,b,nan,cha;   // 最小值,最大值,难度,差值 
}Class[55];
bool cmp(node a,node b){   // 按照难度排序。 
	return a.nan < b.nan;
}
int main(){
	long long n,m,k;
	scanf("%lld%lld%lld",&n,&m,&k);
	for(int i = 1 ; i <= m ; i ++){
		scanf("%lld%lld%lld",&Class[i].a,&Class[i].b,&Class[i].nan);
		Class[i].cha = Class[i].b - Class[i].a;
	}
	sort(Class+1,Class+1+m,cmp);
	memset(dp,0,sizeof(dp));  //初始化为 0  
	for(int i = 1 ; i <= m ; i ++){  // 初始化第一天 
		for(int L = 0 ; L <= Class[i].cha ;L++)
		dp[1][i][L] = Class[i].a + L;
	}
	for(int i = 2 ; i <= n ; i ++){ // 枚举天数 
		for(int j = 1 ; j <= m ; j ++){ // 枚举 哪门课 
			for(int L = 0 ; L <= Class[j].cha ; L ++){
				long long now = Class[j].a + L;  // i天选择j门课获得作业量 
				long long pre1 = now - k;   
				long long pre2 = now / k;    
				for(int x = 1 ; x < j ; x ++){  // 枚举i-1天的难度 
					if(Class[x].nan < Class[j].nan){  // 保证难度严格单调。 
						if(pre1 >= Class[x].a && pre1 <= Class[x].b && dp[i-1][x][pre1 - Class[x].a] != 0){
							dp[i][j][L] = max(dp[i][j][L],dp[i-1][x][pre1 - Class[x].a] + now);
						}
						if(pre2 >= Class[x].a && pre2 <= Class[x].b && now%k == 0 &&dp[i-1][x][pre2 - Class[x].a] != 0){
							dp[i][j][L] = max(dp[i][j][L],dp[i-1][x][pre2 - Class[x].a] + now);
						}	
					}
				}
			}
		}
	}
	long long ans = 0;
	for(int i = 1 ; i <= m ; i ++){
		for(int j = 0 ; j <= Class[i].cha ; j ++){
				ans = max(dp[n][i][j],ans);
			//	cout << ans << endl;
		}
	}
	if(ans){
		printf("YES\n");
		cout << ans << endl;
	}
	else {
		printf("NO\n");
	}

}

猜你喜欢

转载自blog.csdn.net/PK__PK/article/details/82971159
今日推荐