题目大意:

一共有n件食材,每件食材有三个属性,ai,bi和ci,如果在t时刻完成第i样食材则得到ai-t*bi的美味指数,用第i件食材做饭要花去ci的时间。

求最大美味指数之和。

分析:

显然的0/1背包,但是,它与平常的0/1背包不同之处在于:平常的物品不会因为时间的延续而使价值贬值,也就是说,先放a、先放b是无所谓的。

但是这个题,“ai-t*bi”的判断方法,显然相同物品的不同放置顺序,都可能得到不同的答案。

所以必然要排序。

但是怎么排序?

按照ci排?但是不一定时间短的要先做,可能其它食物b太大,贬值的很厉害。

按照bi排?但是先做贬值快的,可能由于做的时间长,仍然可能造成其它剩余食物贬值总和更大。

按照(sumb-bi)*ci排?但是由于不一定做i的时候,其它的所有的食物都留下等着做,损失其实不一定有sumb-bi那么大

按照ai-(sumb-bi)*ci排?但是这其实是只考虑了第一个做谁,仍然可能不是最优子结构。

我们这样考虑:

设身处地地想一想,我们假设已经过了p时间,还剩下两个食材x,y,你会怎么办?

一定会考虑,先做x或者先做y哪个会最大收益。

先做x:

a[x]-(p+c[x])*b[x]+a[y]-(p+c[x]+c[y])*b[y] —— ①

先做y:

a[y]-(p+c[y])*b[y]+a[x]-(p+c[y]+c[x])*b[x] —— ②

对这两个式子化简,得到①>②的条件是c[x]*b[y]<c[y]*b[x].

所以,对于有若干个食物,道理同样如此。

我们先按这个标准排一下序,然后0/1背包即可。

提醒:如果不用滚动数组的话,虽然好理解,但是要记得,不论j>=food[i].c与否,必须要有一个f[i][j]=f[i-1][j]

这里,我定义f[i][j]为,前i个物品,最后一次做完饭是在j时刻。也可以省略第一维。

(至于为什么要排序,假设现在x优于y,如果我们先循环的是x,就代表会先做x,再做y的时候,可以从上一次做完x的时刻转移过来美味程度。

如果y在了前面循环,那么想要同时做x,y,x必须从上一次的某一个y处转移过来,那么这个时候,x一定不是第一个做的。

或者,就算是x想要第一个做,但是y已经循环过去了,不会再从x做完后的时间转移到更靠后的j,也就扔掉了正解的转移路径。)

代码:

  1. #include<bits/stdc++.h>
  2. #define ll long long
  3. using namespace std;
  4. const int N=;
  5. const int T=+;
  6. ll f[T];
  7. int sb;
  8. int n,t;
  9. struct node{
  10. ll a,b,c;
  11. bool friend operator <(node a,node b)
  12. {
  13. return a.c*b.b<b.c*a.b;
  14. }
  15. }foo[N];
  16. int main()
  17. {
  18. cin>>t>>n;
  19. for(int i=;i<=n;i++) scanf("%lld",&foo[i].a);
  20. for(int i=;i<=n;i++) scanf("%lld",&foo[i].b);
  21. for(int i=;i<=n;i++) scanf("%lld",&foo[i].c);
  22. sort(foo+,foo+n+);
  23. for(int i=;i<=n;i++)
  24. for(int j=t;j>=foo[i].c;j--)
  25. {
  26. f[j]=max(f[j],f[j-foo[i].c]+foo[i].a-foo[i].b*j);
  27. }
  28. ll ans=;
  29. for(int i=;i<=t;i++)
  30. ans=max(ans,f[i]);
  31. cout<<ans;
  32. return ;
  33. }

同理的,还有一道考试题:

再过T天就是Kate的生日了,Coffee打算送它一些蛋糕。在Coffee和Kate的世界,蛋糕是做不出来的,而是种出来了。

Coffee收藏着N个蛋糕种子。第i个蛋糕种子需要在室内培育连续Pi天才能长成幼苗,之后将它移栽到室外,再经过Qi天后就会结出一个美味度为Ri的蛋糕。移栽蛋糕苗、为室外的蛋糕浇水以及收取成熟的蛋糕花费的时间对于Coffee来说可以忽略不计,但由于长成幼苗前的蛋糕比较娇嫩,照顾起来也更麻烦,Coffee每天最多只会照顾一棵蛋糕幼苗。

更具体地,如果Coffee在第t0天开始室内培育第i个蛋糕种子,那么它的室内培育工作会占用Coffee第t0..t0+(Pi)-1,并会在t0+Pi+(Qi)-1天结出蛋糕。在t0..t0+(Pi)-1天,Coffee不会开始或同时培养其他种子。

Coffee希望在Kate生日时,送给Kate的蛋糕们的美味度总和尽量大。也就是说,在接下来的T天内,Kate最多能收获蛋糕的美味度总和最大是多少?注意,即使一个蛋糕苗在第T天前已经被移出了室外,只要它在Kate的生日前没能结出蛋糕,它的美味度就不会被计算到总美味度中。

分析:

发现Q这个延时很麻烦,处理的时候还得想之前有没有种过。可以取巧地,假设过完了P天,就立刻熟了,收获了,但是“收获”的这一天不能晚于T-Qi(这个转化就是合法的)

所以就剩一个0/1背包了。

因为对于不同的物品,有不同的背包上界,既然如此,肯定先考虑,把上界低的先放进包里,因为再高了就放不了了。

上界高的,能力大,就可以放到再靠上的包的空间里。

也就是把公共的区间让范围小的先去填充。排序即可。

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<algorithm>
  4. #include<iostream>
  5. using namespace std;
  6. const int N=+;
  7. const int T=+;
  8. int f[N][T];
  9. struct node{
  10. int cost,dis,val;
  11. }ca[N];
  12. int n,t;
  13. bool cmp(node a,node b)
  14. {
  15. if(a.dis!=b.dis) return a.dis>b.dis;
  16. return a.cost<b.cost;
  17. }
  18. int main()
  19. {
  20. scanf("%d%d",&n,&t);
  21. for(int i=;i<=n;i++)
  22. scanf("%d%d%d",&ca[i].cost,&ca[i].dis,&ca[i].val);
  23. sort(ca+,ca+n+,cmp);
  24. for(int i=;i<=n;i++)
  25. {
  26. for(int j=t-ca[i].dis;j>=;j--)
  27. {f[i][j]=f[i-][j];
  28. if(j>=ca[i].cost) f[i][j]=max(f[i][j],f[i-][j-ca[i].cost]+ca[i].val);}
  29. for(int j=;j<=t;j++)
  30. cout<<f[i][j]<<endl;
  31. cout<<endl;
  32. }
  33. int ans=;
  34. for(int i=;i<=t;i++)
  35. ans=max(ans,f[n][i]);
  36. printf("%d",ans);
  37. return ;
  38. }

总结:

1.背包的变式其实是非常多的,总体的定义、循环相差不大,但是关键点多出在排序。

2.排序本质上都是两两之间的物品进行最优解的比较,所以考虑如何排序的时候,可以尝试单独考虑这两个元素之间的大小关系,从而列出式子。

3.背包不能凭感觉瞎想,一定要分析好物品循环的先后顺序。

4.背包本质上还是背包,就是往有限空间里放东西,只是东西千奇百怪罢了,但是考虑方式是可以转化到基础的放东西模型上的。

5.背包物品的循环顺序,本质上就是考虑放物品的先后顺序。不会存在先考虑,却在实际操作中是后放进去的。

洛谷 P1417烹调方案的更多相关文章

  1. [洛谷P1417 烹调方案]贪心+dp

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3211Dream City Time Limit: 1 Second     ...

  2. 洛谷P1417 烹调方案

    题目背景 由于你的帮助,火星只遭受了最小的损失.但gw懒得重建家园了,就造了一艘飞船飞向遥远的earth星.不过飞船飞到一半,gw发现了一个很严重的问题:肚子饿了~ gw还是会做饭的,于是拿出了储藏的 ...

  3. 洛谷 P1417 烹调方案

    题目背景 由于你的帮助,火星只遭受了最小的损失.但gw懒得重建家园了,就造了一艘飞船飞向遥远的earth星.不过飞船飞到一半,gw发现了一个很严重的问题:肚子饿了~ gw还是会做饭的,于是拿出了储藏的 ...

  4. 洛谷P1417 烹调方案【dp】

    题目:https://www.luogu.org/problemnew/show/P1417 题意: 一道菜有$a,b,c$三个值.烧一道菜的时间是$c$.得到的价值是,$a-t*b$其中$t$是菜完 ...

  5. 洛谷 P1417 烹调方案 (01背包拓展)

    一看到这道题就是01背包 但是我注意到价值和当前的时间有关. 没有想太多,直接写,0分 然后发现输入方式不对-- 改了之后只有25分 我知道wa是因为时间会影响价值,但不知道怎么做. 后来看了题解,发 ...

  6. 洛谷 P1417 烹调方案 题解

    题面 这道题是一道典型的排序dp a[i]−b[i]∗(t+c[i])+a[j]−b[j]∗(t+c[i]+c[j]) a[j]−b[j]∗(t+c[j])+a[i]−b[i]∗(t+c[i]+c[j ...

  7. 洛谷1417 烹调方案 dp 贪心

    洛谷 1417 dp 传送门 挺有趣的一道dp题目,看上去接近于0/1背包,但是考虑到取每个点时间不同会对最后结果产生影响,因此需要进行预处理 对于物品x和物品y,当时间为p时,先加x后加y的收益为 ...

  8. 【洛谷】【动态规划/背包】P1417 烹调方案

    由于你的帮助,火星只遭受了最小的损失.但gw懒得重建家园了,就造了一艘飞船飞向遥远的earth星.不过飞船飞到一半,gw发现了一个很严重的问题:肚子饿了~ gw还是会做饭的,于是拿出了储藏的食物准备填 ...

  9. P1417 烹调方案

    P1417 烹调方案 题目提供者tinylic 标签 动态规划 难度 普及+/提高 题目背景 由于你的帮助,火星只遭受了最小的损失.但gw懒得重建家园了,就造了一艘飞船飞向遥远的earth星.不过飞船 ...

随机推荐

  1. C#_Attribute特性

    [AttributeUsage(AttributeTargets.All)]//指定Attribute的使用范围,比如只能在class级别使用 public class Column : Attrib ...

  2. 【亲测有效】Centos安装完成docker后启动docker报错docker: unrecognized service的两种解决方案

    今天在学习Docker的时候 使用yum install docker安装完后启动不了,报错如下: [root@Sakura ~]# service docker start docker: unre ...

  3. BUAAMOOC项目终审报告

    工作总结 我们是歪果仁带你灰开发团队.我们开发的项目是北航学堂(MOOC)的android客户端:BUAAMOOC. 目前我们完成了主要功能,包括UI设计,视频播放,视频下载,学习进度,个人信息等功能 ...

  4. Spring Cloud集成EDAS(替代Eureka)

    https://help.aliyun.com/document_detail/72618.html?spm=5176.7946893.821398.spring-cloud.603123beXemW ...

  5. Windows samba history

    https://blogs.technet.microsoft.com/josebda/2013/10/02/windows-server-2012-r2-which-version-of-the-s ...

  6. [转帖]ASP.NET Core Web服务器 Kestrel和Http.sys 特性详解

    ASP.NET Core Web服务器 Kestrel和Http.sys 特性详解 https://www.cnblogs.com/vipyoumay/p/7525478.html ASP.NET C ...

  7. git 快捷键

    实际上就是弄了个别名 $ git config --global alias.st status $ git config --global alias.ci commit $ git config ...

  8. python排序

    排序算法概览 归并排序的 空间复杂度为O(n) 插入排序 基本思想是每次讲一个待排序的记录,按其关键字大小插入到前面已拍好的子序列中,直到全部完成. 直接插入排序 讲元素L(i)插入到有序序列L[1, ...

  9. linux中tomcat修改错误日志路径

    涉及文件 log4j.properties   (一般开发将该文件放在项目的缺省目录即源包下,在文件系统里,就是在项目的/src/java目录下,缺省的文件名是log4j.properties,这样项 ...

  10. python之列表操作(list)

    # 列表操作功能汇总 print("列表操作功能汇总") list_demo = ['first', 'second', 'thrid', 'fourth'] # 复制list_d ...