2015 南阳CCPC hdu5543 Pick The Sticks(01背包)

来源:互联网 发布:阿里云服务器数据恢复 编辑:程序博客网 时间:2024/05/16 10:35

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5543

题目大意:

在一个狭长的容器里面放一些长木棍,每根木棍的长度和价值都不同,现在通过放置木棍使得能够得到的总价值最大。木棍放置不能重叠,对于任意一根木棍,只要他的重心落在容器里面,就算有一部分出去了,也算能够放下。

题目范围:N<=1000,L<=2000

思路:

对于这样一个问题,如果范围小的话,我们大可以枚举两端的木棍,然后对中间的空间进行01背包处理。但是现在范围较大。

我们可以发现这个问题到最后有三种情况:1、0根木棍在外面。2、1根木棍在外面。3、2根木棍在外面。

所以我们可以考虑多设一个维度。dp[i][j][k]代表前i个棍子占用长度j时候有k根露在外面的最大价值。然后背包即可。

代码:

#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>#define ll long longusing namespace std;pair<ll,ll>pp[1005];ll max(ll a,ll b){    return a>b?a:b;}ll dp[4005][5];int main(){    ll T,n,L,i,j,k,maxi,icase=0,x,y;    scanf("%lld",&T);    while(T--)    {        icase++;        maxi=0;        scanf("%lld%lld",&n,&L);        L=L*2;        for(i=1;i<=n;i++)        {            scanf("%lld%lld",&x,&y);           pp[i]= make_pair(2*x,y);            maxi=max(maxi,y);        }        memset(dp,0,sizeof(dp));        for(i=1;i<=n;i++)            for(j=L;j>=pp[i].first/2;j--)        {            for(int u=0;u<=2;u++)            {                if(u>0)                {                    if(j>=pp[i].first)                   dp[j][u]=max(dp[j][u],dp[j-pp[i].first][u]+pp[i].second);                    dp[j][u]=max(dp[j][u],dp[j-pp[i].first/2][u-1]+pp[i].second);            }                else if(j>=pp[i].first)                    dp[j][u]=max(dp[j][u],dp[j-pp[i].first][u]+pp[i].second);            }        }        printf("Case #%lld: ",icase);        maxi=max(maxi,dp[L][2]);        printf("%lld\n",maxi);    }    return 0;}


0 0