zoukankan      html  css  js  c++  java
  • Proud Merchants (01背包+ 无后效性)

    题目大意:

    给你一些钱 m ,然后在这个国家买东西, 共有 n 件物品,每件物品有  价格 P    价值 V    还有一个很特别的属性 Q, Q 指 你如过想买这件物品 你的手中至少有这钱Q 。 虽然你只要花费 钱P ,但你的手中至少有钱Q,如果不足Q ,不能买。问给你钱M ,列出N件物品,最多能获得多少价值的东西

    分析:

    如果没有Q这个限制条件的话,那么这道题就是一个裸的 01背包的问题

    好多题解上说按照p-q从大到小排序即可,但是至于为什么并没有说透,所以今天总结一下。

    一个问题无论是DP,还是贪心求解,需要满足一个无后效性,其中所谓的无后效性是指:“下一时刻的状态只与当前状态有关,而和当前状态之前的状态无关,当前的状态是对以往决策的总结”。就是说我在当前状态做转移的时候,前面的所有的状态都已经枚举过了,只不过只保留下来了最优解,但是抵达当前状态路径不唯一,仅是最终最优结果唯一

    不考虑q的限制的01背包的状态转移方程是d[j] = max(d[j],d[j--p[i]]+v[i]);

    那么什么时候可以转移呢?j-p[i] 是这个状态的花费,那么m-(j-p[i])是当前我所剩下的钱,只有当m-(j-p[i]) > q[i]的时候,才能转移.

    整理一下就p[i] <= j <=m+ p[i] - q[i]; 可以更新的区间是(p[i],m+q[i] - p[i]) 

    所谓无后效性是指,前面的在更新时对后面的决策无影响。那么后面的d[j-p[i]]这个状态肯定在前面已经更新到了。所以就是说前面的更新的范围应该比后面大。所以就是p1 - q1 > p2-q2;即按照p-q从大到小排序,或者q - p按照从小到大排序才能保证后面的能更新到不丢失状态。

    #include <iostream>
    #include <algorithm>
    #include <string>
    #include <string.h>
    #include <vector>
    #include <map>
    #include <stack>
    #include <set>
    #include <queue>
    #include <math.h>
    #include <cstdio>
    #include <iomanip>
    #include <time.h>
    
    #define LL long long
    #define INF 0x3f3f3f3f
    #define ls nod<<1
    #define rs (nod<<1)+1
    
    using namespace std;
    
    const int maxn = 1e5 + 10;
    
    struct Node {
        int p,q,v;
    }a[510];
    
    bool cmp(Node a,Node b) {
        return a.p - a.q > b.p - b.q;
    }
    
    int dp[5010];
    
    int main() {
        int n,m;
        while (~scanf("%d%d",&n,&m)) {
            memset(dp,0, sizeof(dp));
            for (int i = 1;i <= n;i++) {
                scanf("%d%d%d",&a[i].p,&a[i].q,&a[i].v);
            }
            sort(a+1,a+1+n,cmp);
            for (int i = 1;i <= n;i++) {
                for (int j = m;j >= a[i].q;j--)
                    dp[j] = max(dp[j],dp[j-a[i].p]+a[i].v);
            }
            printf("%d
    ",dp[m]);
        }
        return 0;
    }
  • 相关阅读:
    Windows进程端口相关命令
    SpringMVC获取请求的匹配方法对应的路径
    Feign配置远程调用时携带原请求的token
    LINUX的patch文件 何打patch
    如何制作LINUX的patch文件及如何打patch
    (转) 跟我一起写 Makefile --- 陈皓
    u-boot移植到mini2440,增加DM9000驱动的学习笔记
    DNW PL2303驱动解决问题
    kermit的安装,配置
    wpf中bool按钮三种方式
  • 原文地址:https://www.cnblogs.com/-Ackerman/p/12264573.html
Copyright © 2011-2022 走看看