51nod-1636 教育改革

61 篇文章 0 订阅

题目来源:  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[n][m][d]:  dp[i][j][t]: 前 i 天 第 j 个作业 的作业量为 t+aj时的最大作业量  0<=t<=bj-aj;

转移方程: dp[i][j][t]=max{dp[i-1][k][t/k],dp[i-1][k][t+aj-h-ak]}   (k<j && cj>ck )

Code :

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;

struct node{
	LL l;
	LL r;
	int w;
	bool operator<(const node &p){
		return w<p.w;
	}
};
const int MAX_N=55;
const int MAX_M=55;
const int MAX_S=105;
int n,m,h;
node a[MAX_M];
LL dp[MAX_N][MAX_M][MAX_S];

int main()
{
	ios::sync_with_stdio(false);
	cin>>n>>m>>h;
	for(int i=1;i<=m;++i)
		cin>>a[i].l>>a[i].r>>a[i].w;
	sort(a+1,a+m+1);
	for(int i=1;i<=m;++i)
	{
		LL l=a[i].l,r=a[i].r;
		for(int t=r-l;t>=0;--t)
			dp[1][i][t]=l+t;
	}
	for(int i=2;i<=n;++i)
		for(int j=1;j<=m;++j)
		{
			LL l=a[j].l,r=a[j].r;
			for(int t=r-l;t>=0;--t)
			{
				LL Max=0;
				for(int k=1;k<j;++k)
				{
					if(a[k].w>=a[j].w)	break;
					if((l+t)%h==0){
						LL p=(l+t)/h;
						if(p>=a[k].l&&p<=a[k].r){
							Max=max(Max,dp[i-1][k][p-a[k].l]);
						}
					}
					if(l+t-h>0){
						LL p=l+t-h;
						if(p>=a[k].l&&p<=a[k].r){
							Max=max(Max,dp[i-1][k][p-a[k].l]);
						}
					}
				}
				if(Max)	dp[i][j][t]=Max+l+t;
			}
		}
	LL ans=0;
	for(int i=1;i<=m;++i)
		for(int j=0;j<=100;++j)
			ans=max(ans,dp[n][i][j]);
	if(ans){
		cout<<"YES"<<endl<<ans<<endl;
	}else	cout<<"NO"<<endl;
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值