最近A学校正在实施教育改革。
一个学年由n天组成。A学校有m门课程,每天学生必须学习一门课,一门课程必须在一天内学习完。在学习完第i门课程后,学生们会收到 xi 个家庭作业,其中 xi是区间[ai,bi]里的一个整数 。每门课还有一个属性,就是复杂度 ci 。A学校现在要制他们的课程表,具体要求如下:
·在课程表中,随着天数的增加,课程的复杂度是严格递增的。
·除了第1天,每天的作业量必须是前一天的k倍,或者比前一天多k个作业。(假设第i天的作业量为 xi ,则对于i(1<i≤n)到满足 xi = k+xi−1 或 xi = k⋅xi−1 );
现在,给定天数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;
}