题解 P1417 【烹调方案】

kkksc03

2013-08-12 22:35:37

Solution

By tinylic 如果没有b[i]这个属性的话就是明显的01背包问题。 现在考虑相邻的两个物品x,y。假设现在已经耗费p的时间,那么分别列出先做x,y的代价: a[x]-(p+c[x])\*b[x]+a[y]-(p+c[x]+c[y])\*b[y] (①) a[y]-(p+c[y])\*b[y]+a[x]-(p+c[y]+c[x])\*b[x] (②) 对这两个式子化简,得到①>②的条件是c[x]\*b[y]<c[y]\*b[x]. 发现只要满足这个条件的物品对(x,y),x在y前的代价永远更优。 因此可以根据这个条件进行排序,之后就是简单的01背包了。 ```cpp #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #define LL long long #define maxn 100001 using namespace std; struct node { int a, b, c; }a[maxn]; LL f[maxn], ans; int T, n, i, j; bool cmp(node a, node b) { return (LL)a.c * (LL)b.b < (LL)b.c * (LL)a.b; } int main() { scanf("%d%d", &T, &n); for (i = 0; i < n; i++) scanf("%d", &a[i].a); for (i = 0; i < n; i++) scanf("%d", &a[i].b); for (i = 0; i < n; i++) scanf("%d", &a[i].c); sort(a, a + n, cmp); memset(f, 255, sizeof f); f[0] = 0; for (i = 0; i < n; i++) { for (j = T; j >= 0; --j) if (f[j] != -1 && j + a[i].c <= T) f[j + a[i].c] = max(f[j + a[i].c], f[j] + (LL)a[i].a - (LL)(j + a[i].c) * (LL)a[i].b); } for (i = 0; i <= T; i++) ans = max(ans, f[i]); cout << ans << endl; } ```