算法设计与分析 3.1 小火龙 (附加限制条件的0-1背包)

题目描述:

为了迎接节日,商店街策划了一次”火舞之人“促销大酬宾活动。每个在活动开始当天来商店街消费的客人,都可以在最多抽奖两次,根据抽到的卡片获得不同的优惠。已知卡池里面有红色的小绵羊卡、黑色的小鲨鱼卡、紫色的大尾巴狼卡以及一张看上去就很稀有的眯眯眼天使卡。然而你就比较厉害了,“啪”的一下抽出来一张不在卡池中的橙色小火龙卡。老板表示这是我们下一期活动的顶级卡,不知道怎么的就混进去了,作为补偿,他会向你透露下期活动的优惠内容,你可以提前开始准备参加下一期的促销活动。

在下一期活动中,共有N种商品会进行打折,第i种商品打折后的价格为Ci,原价为Vi,从第Ti天开始出售,每种商品限购一件。如果顾客来的时间早于第Ti天,就无法购买到这件商品。由于你工作很忙,周周007,自然不可能每天去超市。现在你想知道,倘若你只在第X天带了Y块钱去一次超市,最多可以购买到原价总和为多少的商品。

输入格式:

第一行包括两个正整数N,M,表示有N种商品进行促销,有M个购物询问。

接下来的N行,每行包括三个正整数Ci, Vi, Ti, 分别表示每种商品的折后价,原价, 和开放购买的日期。

接下来的M行,每行包括两个正整数Xi和Yi,表示你想知道第Xi天带着Yi去购物最多能买到原价总和多少的商品。

输出格式:

输出包括M行,每行一次整数,表示对应的购物计划所能买的最大原价总和。

样例输入:

5 2
5 5 4
1 3 1
3 4 3
6 2 2
4 3 2
3 8
5 9

样例输出:

10
12

HINT:

对于第一个计划,购买第2,3,5种商品收益最高。
对于第二个计划,购买第1,2,3种商品收益最高。
对于60%的测试数据, N<=200,M<=1000,Ci,Yi,Vi,Ti,Xi<=300。
对于100%的测试数据,
N<=300,M<=105,Ci,Yi<=109,Vi<=300,Ti,Xi<=300。

解法:

首先想到把物品按能购买的天数Ti进行排序,把M次询问转化为M次的0-1背包选择问题,结果存在数组里,最后一次性输出。

#include <iostream>
#include <stdio.h>
#include <algorithm> 
#include <cmath>
#include <cstring> 
using namespace std;
struct rec { int w, v, d; }e[301];
struct node { int d, m, id; }q[100001];
int n, m;
int dp[100000];
int ans[100001];
bool cmp1(rec a, rec b) { return a.d < b.d; }
bool cmp2(node a, node b) { return a.d < b.d; }
int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++)
        scanf("%d%d%d", &e[i].w, &e[i].v, &e[i].d) ;
    for (int i = 1; i <= m; i++)
    {
        scanf("%d%d", &q[i].d, &q[i].m);
        q[i].id = i;
    }
    sort(e + 1, e + n + 1, cmp1);
    sort(q + 1, q + m + 1, cmp2);
    memset(dp, 0x3f, sizeof(dp));
    dp[0] = 0;
    int j = 1;
    for (int i = 1; i <= m; i++)
    {
        while (j <= n && e[j].d <= q[i].d)
        {
            for (int k = n * 300; k >= e[j].v; k--)
                dp[k] = min(dp[k], dp[k - e[j].v] + e[j].w);
            for (int k = n * 300; k; k--)
                dp[k] = min(dp[k], dp[k + 1]);
            j++;
        }
        ans[q[i].id] = upper_bound(dp + 1, dp + n * 300 + 1, q[i].m) - dp - 1;//把算出来的id值存在ans数组里面,因为我们只需要倒着找到最大的id值而已。
    }
    for (int i = 1; i <= m; i++)
        cout << ans[i] << endl;
    return 0;
}

众所周知,出题老师都是老阴比....

眼尖的同学一眼就在题目中发现了,Yi<=10^9,这么大的数字去做0-1背包选择,代码丢进去十有八九就当场去世了。



没错,这是一个大容量背包问题,思路是反过来,不找带Yi钱能买到的最大原价的东西,去找能达到最大原价某个值W下花最小的钱y,如果这个y小于Yi,则表示可以满足。

背包问题简单粗暴,“背包九讲”走一遍,一切都变得简单了。


最后

附上这次优秀作业的演示PPT
链接:https://pan.baidu.com/s/1I_mOKkFHj0Sw1gvLvkmPuA
提取码:869s

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容