HDU5543

来源:互联网 发布:matlab如何编程 编辑:程序博客网 时间:2024/05/16 11:14

Problem: Pick The Sticks
Source: The 2015 China Collegiate Programming Contest
Description: 一个人用长度为L的容器装金条,每条金条有自己的长度和自己的价值。装金条的时候只要金条的重心在容器中那么就可以装,现在问你这个人最多能装走多少价值的黄金。
Solution: 如果没有题目描述中加粗的条件,那么这个问题就是一个01问题,现在有了这个条件,那么我们也是可以考虑的。题中的这个条件无非就揭示了会有不多于两根的金条悬在外面,那么这个时候金条需要的空间就是长度的一半,而且有H根金条悬在外面这种情况可以由H1根悬在外面转移过来。反正我看到这个题目的时候感觉就是01,只不过需要把问题往01上靠而已。DP一直是自己的弱项,希望自己能突破上来吧。对了,这个题目还有一个陷阱,就是只有一条金条的时候无论多长都是可以放的。于是我就特判了一下n=1,交上去也过了,后来越想越不对劲。于是我写了一组n=2的数据测试了一下,发现不对,最后看了下大神的解题报告才发现,我们开始的时候就计算出这些金条价值的最大值。最后比较一下DP的结果和这个最大值就好了。这个地方特别巧妙。
Code(C++):

#include <stdio.h>#define MAX(a,b) ((a)>(b)? (a):(b))const int M=4000+5;const int E=1000+5;typedef long long LL;typedef struct tagNode{    LL len;    LL w;    tagNode(){}    tagNode(int _len,int _w):        len(_len),w(_w){}}Node;int n;LL L;LL dp[M][3];Node nodes[E];int main(){    int N,K=1;    for(scanf("%d",&N);N--;){        scanf("%d%I64d",&n,&L);        L<<=1;        LL l,w;        LL tmp_max=0;        for(int i=0;i<n;i++)            scanf("%I64d%I64d",&l,&w),            l<<=1,            nodes[i]=Node(l,w),            tmp_max=MAX(tmp_max,nodes[i].w);        //if(n==1){        //  printf("Case #%d: %I64d\n",K++,nodes[0].w);        //  continue;        //}        for(int i=0;i<M;i++)            for(int j=0;j<3;j++)                dp[i][j]=0;        for(int i=0;i<n;i++)            for(int j=L;j>=nodes[i].len/2;j--)                for(int k=0;k<3;k++){                    if(j>=nodes[i].len)                        dp[j][k]=MAX(dp[j][k],dp[j-nodes[i].len][k]+nodes[i].w);                    if(k)                        dp[j][k]=MAX(dp[j][k],dp[j-nodes[i].len/2][k-1]+nodes[i].w);                }        LL ans=MAX(MAX(tmp_max,dp[L][0]),MAX(dp[L][1],dp[L][2]));        printf("Case #%d: %I64d\n",K++,ans);    }    return 0;}
0 0
原创粉丝点击