题目链接:http://poj.org/problem?id=2392
题目大意:给定n种积木,每种积木都有一个高度hi,一个数量numi,还有一个限制条件,这个积木所在的位置不能高于maxhi,问能叠起的最大高度。
解题思路:一看到题目觉得水题,之前做的背包容量都是固定的,这题容量是根据每个物品的maxhi而定,枚举容量的时候改动下就可以。于是乎开始敲代码,几分钟就敲完运行下竟然样例都不出。后来发现和maxhi应该有关系,maxhi小的应该要在maxhi大的前面先计算,现在考虑maxhi小的物品为a,大的为b.计算到b的状态有些a用不到,但计算到a的状态b都可以用。如a为1 15 2,b为7 16 2,先计算b的话得到最大的可行高度为14,再用a进行转移得到最大高度15,明显不是最优。而b先计算,可全部用到a能到达的状态,这就保证答案最优。
状态转移方程:if (dp[j-k*cost[i]]) dp[j] = 1; (1<=i<=n,1<=k<=num[i],0<=j<=maxi),复杂度O(N*V*k)(这么高的复杂度竟然可以过,但是用二进制处理也只能快一点)
测试数据:
3
代码:
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define MAX 50000 #define max(a,b) (a)>(b)?(a):(b) struct node { int cost,num,h; }arr[500]; int ans,n,dp[MAX]; int cmp(node a,node b) { return a.h < b.h; } int main() { int i,j,k; while (scanf("%d",&n) != EOF) { for (i = 1; i <= n; ++i) scanf("%d%d%d",&arr[i].cost,&arr[i].h,&arr[i].num); sort(arr+1,arr+1+n,cmp); memset(dp,0,sizeof(dp)); ans = 0, dp[0] = 1; for (i = 1; i <= n; ++i) for (j = arr[i].h; j >= arr[i].cost; --j) for (k = 1; k <= arr[i].num; ++k) if (j >= k * arr[i].cost && dp[j-k*arr[i].cost]) dp[j] = 1,ans = max(ans,j); printf("%d\n",ans); } }
本文ZeroClock原创,但可以转载,因为我们是兄弟。