UESTC1218 2015CCPC DP 0,1背包

来源:互联网 发布:java messagedigest 编辑:程序博客网 时间:2024/06/05 23:52

题意

  • 给你n个小木棍,每根有长度和权值,一维的把它们放到一个长为L的平台上,只要木棍重心在平台上,即可认为可以放上去,问你怎么放,权值最高。
  • n<=1000, L <= 2000

思路

  • 在0,1背包的基础上加一维,维护两端放出去的木棍现在有几个
  • 求出后在和考虑只放一根木棍的情况,和n个木棍的权值求max即可
  • 注意的是,要想到取一半的时候有小数的问题,所以预先把所有长度乘二。

实现

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#include <cmath>using namespace std;const int maxn = 1005;const int maxl = 4005;typedef long long ll;int n,l;int a[maxn];int v[maxn];ll dp[maxl][3];int main(){    int T;    cin>>T;    for (int t=1;t<=T;t++){        scanf("%d%d",&n,&l);        l <<= 1;        for (int i=1;i<=n;i++){            scanf("%d%d",&a[i],&v[i]);            a[i] <<= 1;        }           memset(dp,0,sizeof(dp));        for (int i=1;i<=n;i++){            int tmp = (a[i] >> 1);            for (int j=l;j>=tmp;j--){                for (int k=0;k<3;k++){                    if (j >= a[i]){                        dp[j][k] = max(dp[j][k],dp[j-a[i]][k] + (ll)v[i]);                    }                    if (k > 0){                        dp[j][k] = max(dp[j][k],dp[j-tmp][k-1] + (ll)v[i]);                    }                }            }        }        ll ans = 0;        for (int i=1;i<=n;i++){            ans = max(ans,(ll)v[i]);        }        ans = max(ans,dp[l][2]);        printf("Case #%d: %lld\n",t,ans);    }    return 0;}
0 0
原创粉丝点击