POJ 2392 Space Elevator 和 HDU3466 Proud Merchants

HDU3466的题目链接

题意:2392和3466都是在有01背包的同时也有额外的限制,2392是木板搭天梯,每种木板有一个高度限制,木板的任何地方都不能超出这个高度,而3466是买东西,但是买某一件东西是时,要求拥有的钱多余某个数(买之前的钱)。

题解:这两个问题类似,都是在结果中本来没有顺序的差别,但是因为有了新的限制,有了使用物品先后顺序的差别。考虑最优的结果,一定是容易购买的在后面才买,要求比较高的在前面才买,并且dp背包本身就是枚举,那么只需先对物品进行排序然后在正常dp+限制就好了。关键是排序的方法:应该用两个物品特殊情况来考虑写cmp函数,比如买东西,1和2,先买1再买2可以,但是先买2再买1就不行,把这两个等式写出来,就能写出排序的依据。同理,木板搭天梯也是这样,只是那个比较简单,直接按照限制排序就好。

重点:当有一些限制使得不同购买顺序对结果不一样时,利用两个物品比较来搞出cmp的标准,排序后dp。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <ctype.h>
#include <limits.h>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <set>
#include <bitset>
#define CLR(a) memset(a, 0, sizeof(a))
#define REP(i, a, b) for(int i = a;i < b;i++)
#define REP_D(i, a, b) for(int i = a;i <= b;i++)

typedef long long ll;

using namespace std;

const int maxn = 5000 + 100;
int dp[maxn], n, tot;
struct info
{
    int p, q, v;
};
info a[maxn];

void getDp()
{
    memset(dp, -1, sizeof(dp));
    dp[0] = 0;
    REP_D(i, 1, n)
    {
        for(int j = tot;j >= 0;j--)
        {
            if(j >= a[i].p&&(tot - (j-a[i].p) )>=a[i].q&&dp[j-a[i].p]!=-1&&dp[j-a[i].p]+a[i].v>dp[j])//dp方程,只是多了一个额外限制,其实通过这个限制也能
            {//推出排序标准
                dp[j] = dp[j-a[i].p]+a[i].v;
            }
        }
    }
}
bool cmp(info a, info b)
{
    return a.q - a.p > b.q - b.p;//核心关键,排序标准。
}
void solve()
{
    sort(a + 1, a+1+n, cmp);
    getDp();
    int ans = 0;
    REP_D(i, 0, tot)
    {
        ans = max(ans, dp[i]);
    }
    printf("%d\n", ans);
}

int main()
{
   // freopen("2Bin.txt", "r", stdin);
    //freopen("3Bout.txt", "w", stdout);
    while(scanf("%d%d", &n, &tot) != EOF)
    {
        REP_D(i, 1, n)
        {
            scanf("%d%d%d", &a[i].p, &a[i].q, &a[i].v);
        }
        solve();
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值