zoukankan      html  css  js  c++  java
  • HDU

    传送门

    传送门

    题意:有n件物品,你的钱数是m。每件物品最多买一次,且每件物品除了价格p和价值v外,还有限制q,代表你当前至少有钱数q时,商家才愿意把东西卖给你。求使用不多于m的钱最多获得的价值。

    题目就容易让人想到01背包,但不同的是,它多了一个条件,导致这道题不满足dp问题的无后效性。那么我们可以考虑先对贪心的决定物品的选择顺序,再利用01背包求解。

    首先会想到贪心地优先选择Q值大的物品,反例:

    2(n) 6(m)

    3(p1) 5(q1)

    1(p2) 4(q2)

    然后就会想到优先买P值小的物品,因为这样下一步操作有更多的钱,有更好的选择性。还是反例:

    2(n) 4(m)

    1(p1) 2(q1)

    2(p2) 4(q2)

    所以我们就会想到优先购买pi-qi最小的物品。假设由于操作顺序的不同,我们能买的物品数量不同。以上面的数据为例,能买一件物品(先买物品一),也可能买两件物品(先买物品二),那么我们有q1+p2 <= m < p1 + q2,移项则有p2-q2<p1-q1,也就是要优先买p-q小的物品。

    定义dp[i]表示以钱数i最多能买到的物品价值。对数组排序后就是有选择顺序的01背包问题。a[1]存储pi-qi最小的物品。如果我们写的是当前状态是可以由那些状态转移得到(区别于当前状态可以转移到那些状态),那么第一层循环方向应该是N到1的。

    或者说从无后效性的角度考虑,即要求每个子问题的决策不能对后面其他未解决的问题产影响,所以我们应当是从大状态转移到小状态(或者理解为当前状态为前面已经更新过的某个状态的子集),就是后面更新的dp[j] = max(dp[j], dp[j - a[i].p] + a[i].v);中的j-a[i].p的状态应当在前面已经更新过了。所以要优先处理出q-p的值小的

    怎么32行那行判断语句不加也能AC不会越界的,是数据默认了q大于p吗...

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #define INF 0x3f3f3f3f
     6 #define MOD 1000000007
     7 using namespace std;
     8 typedef long long LL;
     9 
    10 const int maxn = 5e2 + 10;
    11 const int maxm = 5e3 + 10;
    12 
    13 struct node {
    14     int p, q, v;
    15 }a[maxn];
    16 int dp[maxm];
    17 int N, M;
    18 
    19 bool cmp(struct node& A, struct node& B) {
    20     return (A.p - A.q) < (B.p - B.q);
    21 }
    22 
    23 int main(int argc, const char * argv[]) {
    24     while (~scanf("%d%d", &N, &M)) {
    25         for (int i = 1; i <= N; i++) {
    26             scanf("%d%d%d", &a[i].p, &a[i].q, &a[i].v);
    27         }
    28         sort(a + 1, a + 1 + N, cmp);
    29         memset(dp, 0, sizeof(dp));
    30         for (int i = N; i >= 1; i--) {
    31             for (int j = M; j >= a[i].q; j--) {
    32                 if (j < a[i].p) break;//
    33                 dp[j] = max(dp[j], dp[j - a[i].p] + a[i].v);
    34             }
    35         }
    36         printf("%d
    ", dp[M]);
    37     }
    38     return 0;
    39 }
  • 相关阅读:
    349、两个数组的交集 | JS集合
    JS集合Set
    JS里的队列和链表
    使用链表指针获取JSON的节点值
    141、环形链表 | JS-链表
    83、删除排序链表中的重复元素 | JS-链表
    2、两数相加 | JS-链表
    事件循环与任务队列
    933、最近的请求次数 | JS-队列
    栈JS实现
  • 原文地址:https://www.cnblogs.com/xFANx/p/7407402.html
Copyright © 2011-2022 走看看