[luoguP1417] 烹調方案(背包DP)
阿新 • • 發佈:2017-06-21
明顯 tiny -- spa getchar pre 代碼 long -1
傳送門
By tinylic
如果沒有b[i]這個屬性的話就是明顯的01背包問題。
現在考慮相鄰的兩個物品x,y。假設現在已經耗費p的時間,那麽分別列出先做x,y的代價:
a[x]-(p+c[x])*b[x]+a[y]-(p+c[x]+c[y])*by
a[y]-(p+c[y])*b[y]+a[x]-(p+c[y]+c[x])*bx
對這兩個式子化簡,得到①>②的條件是c[x]*b[y]<c[y]*b[x].
發現只要滿足這個條件的物品對(x,y),x在y前的代價永遠更優。
因此可以根據這個條件進行排序,之後就是簡單的01背包了。
然而我看這個DP方程還不是完全的01背包,應該是 f[i] 表示到時刻 i 的最優解,且時刻 i 必須得用
代碼
#include <cstdio> #include <iostream> #include <algorithm> #define N 100001 #define LL long long #define max(x, y) ((x) > (y) ? (x) : (y)) int T, n; LL ans, f[N]; struct node { LL a, b, c; }p[51]; inline int read() { int x = 0, f = 1; char ch = getchar(); for(; !isdigit(ch); ch = getchar()) if(ch == ‘-‘) f = -1; for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - ‘0‘; return x * f; } inline bool cmp(node x, node y) { return x.c * y.b < y.c * x.b; } int main() { int i, j; T = read(); n = read(); for(i = 1; i <= n; i++) p[i].a = read(); for(i = 1; i <= n; i++) p[i].b = read(); for(i = 1; i <= n; i++) p[i].c = read(); std::sort(p + 1, p + n + 1, cmp); for(i = 1; i <= n; i++) for(j = T; j >= p[i].c; j--) { f[j] = max(f[j], f[j - p[i].c] + p[i].a - j * p[i].b); ans = max(ans, f[j]); } printf("%lld\n", ans); return 0; }
[luoguP1417] 烹調方案(背包DP)