原题链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1636
思路:先按难度系数排序,然后定义dp[i][j][k]表示,第i天安排第j门课程,作业量为 第j们课程的最小作业量+k的前i天最大作业量之和,之所以这样定义k,是因为课程的最小最大作业量范围太大,但是差值很小,所以可以定义为在区间内的位置来定义,然后转移就好
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int MOD = 1e9 + 7;
const int MAXN = 1e5 + 5;
const double PI = acos(-1.0);
struct crouse {
long long a, b;
int c;
bool operator < (const crouse&cr)const {
return c < cr.c;
}
}crouses[55];
long long dp[55][55][105];
int n, m, k;
void solve() {
memset(dp, -1, sizeof(dp));
for (int i = 1; i <= m; i++) {
for (int j = 0; j <= crouses[i].b - crouses[i].a; j++) {
dp[1][i][j] = crouses[i].a + j;
}
}
for (int i = 2; i <= n; i++) {
for (int j = 1; j <= m; j++) {
for (int num = 0; num <= crouses[j].b - crouses[j].a; num++) {
for (int t = 1; crouses[t].c < crouses[j].c; t++) {
long long v = crouses[j].a + num - k;
if (crouses[t].a <= v&&crouses[t].b >= v && dp[i - 1][t][v - crouses[t].a] != -1) {
dp[i][j][num] = max(dp[i][j][num], dp[i - 1][t][v - crouses[t].a] + num + crouses[j].a);
}
v += k;
if (v%k == 0 && crouses[t].a <= v / k && crouses[t].b >= v / k && dp[i - 1][t][v / k - crouses[t].a] != -1) {
dp[i][j][num] = max(dp[i][j][num], dp[i - 1][t][v / k - crouses[t].a] + num + crouses[j].a);
}
}
}
}
}
}
int main() {
scanf("%d %d %d", &n, &m, &k);
for (int i = 1; i <= m; i++) {
scanf("%lld %lld %d", &crouses[i].a, &crouses[i].b, &crouses[i].c);
}
sort(crouses + 1, crouses + 1 + m);
solve();
long long ans = -1;
for (int i = 1; i <= m; i++) {
for (int j = 0; j <= crouses[i].b - crouses[i].a; j++) {
ans = max(ans, dp[n][i][j]);
}
}
if (ans == -1)printf("NO\n");
else printf("YES\n%lld\n", ans);
return 0;
}