n个物品有Deadline,拿物品需要花费时间,问取得最大价值的方案。
本质是个01背包,先按时间排序,然后把花费的时间作为背包就行了。
主要就是找方案,倒过来找发生转移的就行了。
太菜了真的不会打CF,每次都要掉分
/** @Date : 2017-09-25 22:28:30 * @FileName: E.cpp * @Platform: Windows * @Author : Lweleth ([email protected]) * @Link : https://github.com/ * @Version : $Id$ */ #include <bits/stdc++.h> #define LL long long #define PII pair<int ,int> #define MP(x, y) make_pair((x),(y)) #define fi first #define se second #define PB(x) push_back((x)) #define MMG(x) memset((x), -1,sizeof(x)) #define MMF(x) memset((x),0,sizeof(x)) #define MMI(x) memset((x), INF, sizeof(x)) using namespace std; const int INF = 0x3f3f3f3f; const int N = 2e5+20; const double eps = 1e-8; int n; int dp[110][3000]; struct yuu { int v, c, d, idx; }a[200]; int cmp(yuu a, yuu b) { if(a.d != b.d) return a.d < b.d; return a.c < b.c; } int main() { cin >> n; int sum = 0; for(int i = 1; i <= n; i++) { scanf("%d%d%d", &a[i].c, &a[i].d, &a[i].v), a[i].idx = i; sum += a[i].c; } sort(a + 1, a + n + 1, cmp); MMF(dp); int ma = 0; int pos = 0; for(int i = 1; i <= n; i++) { for(int j = 0; j <= sum; j++) { if(j < a[i].d && j >= a[i].c) dp[i][j] = max(dp[i - 1][j - a[i].c] + a[i].v, dp[i - 1][j]); else dp[i][j] = dp[i - 1][j]; if(ma < dp[i][j]) pos = j, ma = dp[i][j]; } } vector<int>q; for(int i = n; i >= 1; i--) { if(pos > a[i].d || pos < a[i].c || dp[i - 1][pos] >= dp[i - 1][pos - a[i].c] + a[i].v) continue; pos -= a[i].c; q.PB(i); } reverse(q.begin(), q.end()); printf("%d\n", ma); printf("%d\n", q.size()); for(auto i : q) printf("%d ", a[i].idx); printf("\n"); return 0; }
时间: 2024-11-05 11:24:53