51nod1636 教育改革

1636教育改革
题目来源: CodeForces
基准时间限制: 1 秒 空间限制: 131072 KB 分值: 20 难度:3级算法题
收藏
关注
取消关注

最近A学校正在实施教育改革。

一个学年由n天组成。A学校有m门课程,每天学生必须学习一门课,一门课程必须在一天内学习完。在学习完第i门课程后,学生们会收到  xi  个家庭作业,其中  xi[ai,bi]  。每门课还有一个属性,就是复杂度  ci  。A学校现在要制他们的课程表,具体要求如下:

·在课程表中,随着天数的增加,课程的复杂度是严格递增的。

·除了第1天,每天的作业量必须是前一天的k倍,或者比前一天多k个作业。(假设第i天的作业量为  xi  ,则对于i(1<i≤n)到满足  xi  k+xi1  或  xi  kxi1  );

现在,给定天数n,系数k,和m门课程的ai,bi,ci(1≤i≤m)。要求计算一个学年可以安排最大的总作业量(  ni=1xi  )是多少。


Input
单组测试数据
第一行,三个由空格隔开的整数n,m,k(1≤n≤m≤50,1≤k≤100),表示一个学年的天数,课程的数量,和作业增量系数。
接下来的m行,
每行有三个整数,ai,bi,ci(1≤ai≤bi≤10^16,bi-ai≤100,1≤ci≤100)
分别表示第i门课程的最小作业量,和最多作业量,以及复杂度。
不同的课程可以有相同的复杂度。课程编号从1到m。
Output
如果有可行方案,第一行输出“YES”(没有引号),第二行输出最大的作业量。
如果没有可行方案,则输出一行“NO”(没有引号)。
Input示例
4 5 2
1 10 1
1 10 2
1 10 3
1 20 4
1 100 5
Output示例
YES
78
 
  
 
  
思路:dp[i][j][k] 表示前i门课程选了j门且第j门是第i个课程的总作业数。
code:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int AX = 1e2+6;
int n , m , K;
struct Node
{
	LL l,r,c;
}a[AX];
LL dp[52][52][AX];

bool cmp( const Node &a , const Node &b ){
	return a.c < b.c;
}
int main(){
	scanf("%d%d%d",&n,&m,&K);
	for( int i = 1 ; i <= m ; i++ ){
		scanf("%lld%lld%lld",&a[i].l,&a[i].r,&a[i].c);
	}
	sort( a + 1 , a + m + 1 , cmp );
	memset(dp,-1,sizeof(dp));

	for( int i = 1 ; i <= m ; i ++ ){
		for( LL k = a[i].l ; k <= a[i].r ; k++ ){
			dp[i][1][k-a[i].l] = k;
			for( int t = m ; a[t].c > a[i].c ; t-- ){
				if( k + K >= a[t].l && k + K <= a[t].r ){
					for( int j = min( i , n - 1 ) ; j ; j-- ){
						if( dp[i][j][k-a[i].l] > 0 ){
							dp[t][j+1][k+K-a[t].l] = max( dp[t][j+1][k+K-a[t].l] , dp[i][j][k-a[i].l] + k + K );
						}
					}
				}
				if( k * K >= a[t].l && k * K <= a[t].r ){
					for( int j = min( i , n - 1 ) ; j ; j-- ){
						if( dp[i][j][k-a[i].l] > 0 ){
							dp[t][j+1][k*K-a[t].l] = max( dp[t][j+1][k*K-a[t].l] ,dp[i][j][k-a[i].l] + K * k );
						}
					}
				}
			}
		}
	}
	LL res = -1;
	for( int i = 1 ; i <= m ; i++ ){
		for( int k = a[i].r - a[i].l ; k >= 0 ; k-- ){
			res = max( res , dp[i][n][k] );
		}
	}
	if( res == -1 ){
		printf("NO\n");
	}else{
		printf("YES\n%lld\n",res);
	}
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值