zoukankan      html  css  js  c++  java
  • [HDOJ5543]Pick The Sticks(DP,01背包)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5543

    题意:往长为L的线段上覆盖线段,要求:要么这些线段都在L的线段上,要么有不超过自身长度一半的部分在线段外面,最多有两条这样的线段(在两头)。

    dp(i,j,k)表示前i个线段覆盖在长度为j的线段上,期中有k个线段不完全在这个线段上的最大价值。考虑线段长度的奇偶问题,所以事先把L和其他线段长度乘2,以便操作。所以枚举所有线段,一般情况,就是01背包的问题,dp(i,j,k)=max(dp(i,j,k), dp(i-1,j-w(i),k)+v(i))。当枚举到k不是0的时候,还需要更新两端放的情况:dp(i,j,k)=max(dp(i,j,k),dp(i-1,j-w(i)/2,k-1)+v(i))。直接取w(i)/2是没有关系的,因为我们在这里希望可以贪心地尽可能地少占用当前L上的长度。

    还有一个trick:L=1的时候这么搞。这时L当成一个支点,只能放一个。所以要提前处理所有线段的最大价值。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 typedef long long LL;
     5 const int maxn = 5010;
     6 int w[maxn], v[maxn];
     7 int n, L;
     8 LL dp[maxn][3];
     9 LL ret;
    10 
    11 int main() {
    12   freopen("in", "r", stdin);
    13   int T, _ = 1;
    14   scanf("%d", &T);
    15   while(T--) {
    16     scanf("%d %d", &n, &L);
    17     memset(dp, 0, sizeof(dp));
    18     ret = 0; L <<= 1;
    19     for(int i = 1; i <= n; i++) {
    20       scanf("%d %d", &w[i], &v[i]);
    21       w[i] <<= 1;
    22       ret = max(ret, (LL)v[i]);
    23     }
    24     for(int i = 1; i <= n; i++) {
    25       for(int j = L; j >= w[i]/2; j--) {
    26         for(int k = 0; k <= 2; k++) {
    27           if(j >= w[i]) dp[j][k] = max(dp[j][k], dp[j-w[i]][k]+v[i]);
    28           if(k) dp[j][k] = max(dp[j][k], dp[j-w[i]/2][k-1]+v[i]);
    29            ret = max(ret, dp[j][k]);
    30         }
    31       }
    32     }
    33     printf("Case #%d: %lld
    ", _++, ret);
    34   }
    35   return 0;
    36 }
  • 相关阅读:
    Kafka项目实战-用户日志上报实时统计之应用概述
    ElasticSearch实战-编码实践
    ElasticSearch实战-入门
    Django如何渲染markdown
    理解相似矩阵
    从向量空间的角度来理解方程组有无解的问题
    凸优化学习笔记(1)-基础概念
    Django如何与JQuery进行数据通信?
    JQuery学习笔记之属性与样式
    JQuery学习笔记之选择器
  • 原文地址:https://www.cnblogs.com/kirai/p/5955455.html
Copyright © 2011-2022 走看看