该题与poj 1742的思路基本一致:http://www.cnblogs.com/sevenun/p/5442279.html(多重背包)
题意:给你n个电梯,第i个电梯高h[i],数量有c[i]个,但是每个电梯所在高度不能超过a[i].
求问,怎么样的建造方案能够使电梯能够达到最大高度
思路:首先,必然要使电梯按a[i]进行排序,a[i]最小的电梯先建造。例如,电梯1,只能在高度20以下建造,而电梯2能在高度50以下建造,我当然先建造电梯1,否则如果先建造电梯2,就会导致我建造的高度早早超过了20,这样就无法充分利用了电梯1。
动态规划,想到转移方程为d[i][j],前i个电梯建造到高度j时,第i个电梯所剩余多少个。
默认d[i][j]为-1,代表前i个电梯无法达到高度j。
对于d[i][j],如果前i-1个电梯的建造已能够达到高度j,那么到高度j自然就不需要第i个电梯,所以就剩余c[i]个电梯
如果前i-1个电梯的建造不能达到高度j,那么我自然就要利用第i个电梯看看是否能够达到高度j,所以d[i][j] = d[i][j-h[i]]-1。
滚动数组:由于n最大为400,且a[i]最大为40000,那么由上面的定义,那么数组肯定就要达到400*40000了,感觉内存不够了
所以观察方程可知,d[i][j]的计算只会涉及到前一行和当前行,所以可以利用滚动数组,从而减少内存的使用。
AC代码:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int K = 404; const int H = 40005; int n,d[2][H]; struct node { int a,c,h; }w[K]; int cmp(node n1, node n2) { return n1.a < n2.a; } void solve() { int f = 1; memset(d, -1, sizeof(d)); sort(w,w+n,cmp); for(int j = 0; j*w[0].h <= w[0].a; j++) d[0][j*w[0].h] = w[0].c - j; for(int i = 1; i < n; i++) { d[f][0] = w[i].c; for(int j = 1; j <= min(w[i].a, H); j++) { if(d[!f][j] >= 0) d[f][j] = w[i].c; else if(j >= w[i].h) d[f][j] = d[f][j-w[i].h]-1; else d[f][j] = -1; d[!f][j] = -1; } d[!f][0] = -1; f = !f; } int ans = 0; for(int i = w[n-1].a; i >= 0; i--) { ans = i; if(d[!f][i]>= 0) break; } printf("%d\n", ans); } int main() { //freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); while(~scanf("%d", &n)) { for(int i = 0; i < n; i++) scanf("%d %d %d", &w[i].h, &w[i].a, &w[i].c); solve(); } return 0; }
时间: 2024-10-14 09:45:37