题目描述:
1636 教育改革
最近A学校正在实施教育改革。
一个学年由n天组成。A学校有m门课程,每天学生必须学习一门课,一门课程必须在一天内
学习完。在学习完第i门课程后,学生们会收到 xixi 个家庭作业,其中 xi是区间[ai,bi]里的一个
整数xi是区间[ai,bi]里的一个整数 。每门课还有一个属性,就是复杂度 cici 。A学校现在要制他
们的课程表,具体要求如下:
在课程表中,随着天数的增加,课程的复杂度是严格递增的。
除了第1天,每天的作业量必须是前一天的k倍,或者比前一天多k个作业。(假设第i天的作业
量为 xixi ,则对于i(1<i≤n)到满足 xi = k+xi−1xi = k+xi−1 或 xi = k⋅xi−1xi = k·xi−1 );
现在,给定天数n,系数k,和m门课程的ai,bi,ci(1≤i≤m)。要求计算一个学年可以安排最
大的总作业量( 总作业量的表达式是∑ni=1xi总作业量的表达式是∑i=1nxi )是多少。
收起
输入
单组测试数据 第一行,三个由空格隔开的整数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。输出
如果有可行方案,第一行输出“YES”(没有引号),第二行输出最大的作业量。 如果没有可行方案,则输出一行“NO”(没有引号)。输入样例
4 5 2 1 10 1 1 10 2 1 10 3 1 20 4 1 100 5输出样例
YES 78
思路:
状态描述:
dp【i】【j】【k】:将第 i 门课程安排在第 j 天,布置K+arr[i].a的作业量
时前 j 天获得的最大最大作业量。
递推关系:
值比
小的课程号
减去/除以相对限制
。
PS:第一天的特判、k-相应限制能否与目标课程适应、数组下标负数的防止、要求难度严格单增。
目标状态:
dp【i】【n】【k】。
代码实现:
//关键代码
if(arr[i].c!=arr[l].c&&arr[i].a+k-kn>=arr[l].a&&
arr[i].a+k-kn<=arr[l].b&&dp[l][j-1][arr[i].a+k-kn-arr[l].a])
dp[i][j][k]=max(dp[i][j][k],dp[l][j-1][arr[i].a+k-kn-arr[l].a]+arr[i].a+k);
if(arr[i].c!=arr[l].c&&(arr[i].a+k)/kn>=arr[l].a&&
(arr[i].a+k)/kn<=arr[l].b&&dp[l][j-1][(arr[i].a+k)/kn-arr[l].a])
dp[i][j][k]=max(dp[i][j][k],dp[l][j-1][(arr[i].a+k)/kn-arr[l].a]+k+arr[i].a);
#include<iostream>
#include<cstring>
#include<cmath>
#include<stack>
#include<algorithm>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int N=4*2e5+100;
struct Node {
LL a,b,c;
} arr[N];
bool cmp1(Node aa,Node bb) {
return aa.c<bb.c;
}
LL dp[52][52][102];
int main() {
int n,m,kn;
LL ans;
while(cin>>n>>m>>kn) {
ans=0;
memset(dp,0,sizeof(dp));
for(int i=1; i<=m; i++) {
cin>>arr[i].a>>arr[i].b>>arr[i].c;
}
sort(arr+1,arr+1+m,cmp1);
for(int i=1; i<=m; i++)
for(int j=1; j<=n; j++)
for(int k=0; k<=arr[i].b-arr[i].a; k++) {
if(j==1) {
dp[i][j][k]=arr[i].a+k;
} else {
for(int l=1; l<i; l++) {
//这个 if 的 条件很关键
if(arr[i].c!=arr[l].c&&arr[i].a+k-kn>=arr[l].a&&
arr[i].a+k-kn<=arr[l].b&&dp[l][j-1][arr[i].a+k-kn-arr[l].a]) {
dp[i][j][k]=max(dp[i][j][k],
dp[l][j-1][arr[i].a+k-kn-arr[l].a]+arr[i].a+k);
}
}
}
if((arr[i].a+k)%kn==0) {
for(int l=1; l<i; l++) {
//这个 if 的 条件很关键
if(arr[i].c!=arr[l].c&&(arr[i].a+k)/kn>=arr[l].a&&
(arr[i].a+k)/kn<=arr[l].b&&dp[l][j-1][(arr[i].a+k)/kn-arr[l].a]) {
dp[i][j][k]=max(dp[i][j][k],
dp[l][j-1][(arr[i].a+k)/kn-arr[l].a]+k+arr[i].a);
}
}
}
}
for(int i=1; i<=m; i++) {
for(int j=0; j<=arr[i].b-arr[i].a; j++) {
ans=max(ans,dp[i][n][j]);
}
}
if(ans) {
cout<<"YES"<<endl;
cout<<ans<<endl;
} else {
cout<<"NO"<<endl;
}
}
return 0;
}
THE END;