Pick apples

Time Limit: 1000MS Memory limit: 165536K

题目描写叙述

Once ago, there is a mystery yard which only produces three kinds of apples. The number of each kind is infinite. A girl carrying a big bag comes into the yard. She is so surprised because she has never seen so many apples before. Each kind
of apple has a size and a price to be sold. Now the little girl wants to gain more profits, but she does not know how. So she asks you for help, and tell she the most profits she can gain.

输入

In the first line there is an integer T (T <= 50), indicates the number of test cases.

In each case, there are four lines. In the first three lines, there are two integers S and P in each line, which indicates the size (1 <= S<= 100) and the price (1 <= P <= 10000) of this kind of apple.

In the fourth line there is an integer V,(1 <= V <= 100,000,000)indicates the volume of the girl's bag.

输出

For each case, first output the case number then follow the most profits she can gain.

演示样例输入

  1. 1 1
  1. 1 2
  1. 1 3
  1. 1 6

演示样例输出

  1. Case 1: 6

提示

 

来源

2012年"浪潮杯"山东省第三届ACM大学生程序设计竞赛

解题思路:

从昨天赛完就開始弄这道题,当时做的时候第一感觉就是全然背包,可是数据量太大了,直接全然背包肯定会超时。赛后看解题报告才知道这题用的是大范围贪心,小范围全然背包,这个也好懂,看了网上AC的代码小范围用的是1000,但这个今天被老师证实是错误的,这题后台測试数据不完好,比方老师给的这组測试数据:

98 99

99 100

100 101

2000        这组測试数据用小范围为1000的代码測试结果为2000,可是正确答案应该是2020,尽管第一种是最优的东西,可是这里我们要所有选择第三种100 101的才是正确答案。所以小范围为1000是错误的,这里的小范围应该是三种物品容量的最小公倍数,即100*100*100,用1000000就能够了。做这个题花了真不少功夫,整个上午差点儿相同就是在runtime error 和 wrong answer中度过的。找错找了非常久。注意的是:限定的容量V要用long long类型,dp[]数组也要用
long long类型。dp[]数组不能仅仅开1000000个,要尽量大点,由于在贪心部分仅仅选择最优的那种物品,可是大于1000000的那部分不一定能整除该物品的容量,也就是说可能会剩余一部分容量加到1000000里面一起用全然背包来做。这个就是无数次runtime error的原因所在。后来又看到一种解法,特别巧妙,没实用到贪心和背包,就是枚举除了最优物品之外的两外两种背包的选择的个数,这里有一个限定条件,那就是不是最优物品的物品被选择的个数一定比最优物品的容量要小,

比方这组測试数据;

最优物品 3   6

其它         2    3      选一个 2 3 选两个  4  6  选三个6  9 但这时候我们选2个最优物品的情况是 6 12,显然比选三个其它物品要好,也就是说其它物品可能选的个数的情况有0 个,1个,2个。这些都是有可能的,本题背包的容量都小于100,所以两层循环枚举其它两种物品被选择的个数,在计算中取最大值就能够了,复杂度为0(100*100)。

第一种方法(排序做的贪心+全然背包):

  1. #include <iostream>
  2. #include <string.h>
  3. #include <algorithm>
  4. using namespace std;
  5. const int lcm=1000000;//三种类size的最小公倍数
  6. long long dp[lcm*2+2],V;//dp数组要开的足够大,不能仅仅开lcm个,原因见后面凝视,还有V要用long long
  7.  
  8. struct N
  9. {
  10. int s,p;
  11. double pri;
  12. }node[3];
  13.  
  14. bool cmp(N a ,N b)
  15. {
  16. return a.pri<b.pri;
  17. }
  18. long long maxll(long long a,long long b)
  19. {
  20. return a>b?a:b;
  21. }
  22.  
  23. void compack()//全然背包
  24. {
  25. memset(dp,0,sizeof(dp));
  26. for(int i=0;i<3;i++)
  27. for(int j=node[i].s;j<=V;j++)
  28. dp[j]=maxll(dp[j],dp[j-node[i].s]+node[i].p);
  29. }
  30.  
  31. int main()
  32. {
  33. int t;cin>>t;int c=1;
  34. while(t--)
  35. {
  36. for(int i=0;i<3;i++)
  37. {
  38. cin>>node[i].s>>node[i].p;
  39. node[i].pri=node[i].s*1.0/node[i].p;
  40. }
  41. cin>>V;
  42. if(V<=lcm)//小范围直接全然背包
  43. {
  44. compack();
  45. cout<<"Case "<<c++<<": "<<dp[V]<<endl;
  46. }
  47. else
  48. {
  49. sort(node,node+3,cmp);//排序,最优的在第一个
  50. V-=lcm;//超出1000000的部分
  51. long long ans=0;
  52. ans=ans+(V/node[0].s*node[0].p);//贪心部分选择第一个所获得的价值
  53. V=lcm+(V-V/node[0].s*node[0].s);//这里解释了为什么dp要开的足够大,不能仅仅开lcm个,由于在贪心部分不一定能整除,有余下的部分
  54. compack();//全然背包
  55. cout<<"Case "<<c++<<": "<<ans+dp[V]<<endl;
  56. }
  57. }
  58. return 0;
  59. }

另外一种方法(未排序的贪心+全然背包):

  1. #include <iostream>
  2. #include <string.h>
  3. using namespace std;
  4. const int lcm=1000000;
  5. long long dp[lcm*2+2],V;
  6. int s[5],p[5];
  7.  
  8. void compack()
  9. {
  10. memset(dp,0,sizeof(dp));
  11. for(int i=0;i<3;i++)
  12. for(int j=s[i];j<=V;j++)
  13. {
  14. if(dp[j]<dp[j-s[i]]+p[i])
  15. dp[j]=dp[j-s[i]]+p[i];
  16. }
  17. }
  18. int main()
  19. {
  20. int t;cin>>t;int c=1;
  21. while(t--)
  22. {
  23. double pr,temp=0;
  24. int id;
  25. for(int i=0;i<3;i++)
  26. {
  27. cin>>s[i]>>p[i];
  28. pr=1.0*p[i]/s[i];
  29. if(temp<pr)
  30. {
  31. temp=pr;
  32. id=i;
  33. }
  34. }
  35. cin>>V;
  36.  
  37. if(V<=lcm)
  38. {
  39. compack();
  40. cout<<"Case "<<c++<<": "<<dp[V]<<endl;
  41. }
  42. else
  43. {
  44. long long ans=(V-lcm)/s[id]*p[id];
  45. V=V-(V-lcm)/s[id]*s[id];
  46. compack();
  47. cout<<"Case "<<c++<<": "<<ans+dp[V]<<endl;
  48. }
  49. }
  50. }

第三种方法(枚举未排序):

  1. #include <iostream>
  2. #include <stdio.h>
  3. using namespace std;
  4. int s[4],p[4];
  5.  
  6. long long llmax(long long a,long long b)
  7. {
  8. return a>b?a:b;
  9. }
  10. int main()
  11. {
  12. int t;
  13. cin>>t;
  14. int c=1;
  15. while(t--)
  16. {
  17. for(int i=1; i<=3; i++)
  18. cin>>s[i]>>p[i];
  19. int V;
  20. cin>>V;
  21. int k1=1,k2,k3;
  22. for(int i=2; i<=3; i++)
  23. {
  24. if(p[i]*s[k1]>p[k1]*s[i])//推断优先级
  25. k1=i;
  26. }
  27. if(k1==1){k2=2;k3=3;};//k1是最优的物品,k2,k3是谁没有关系
  28. if(k1==2){k2=1,k3=3;};
  29. if(k1==3){k2=1,k3=2;};
  30. long long ans=0;
  31. for(int i=0; i<s[k1]; i++)//枚举
  32. {
  33. for(int j=0; j<s[k1]; j++)
  34. {
  35. long long temp=i*s[k2]+j*s[k3];
  36. if(temp>V)
  37. break;
  38. else
  39. {
  40. long long v=V-temp;
  41. ans=llmax(ans,v/s[k1]*p[k1]+i*p[k2]+j*p[k3]);//选最大值
  42. }
  43. }
  44. }
  45. cout<<"Case "<<c++<<": "<<ans<<endl;
  46. }
  47. return 0;
  48. }

第四种方法(排序枚举):

  1. #include <iostream>
  2. #include <stdio.h>
  3. #include <algorithm>
  4. using namespace std;
  5.  
  6. struct N
  7. {
  8. int s,p;
  9. double pri;
  10. }node[4];
  11.  
  12. bool cmp(N a,N b)
  13. {
  14. if(a.pri<b.pri)
  15. return true;
  16. return false;
  17. }
  18.  
  19. long long llmax(long long a,long long b)
  20. {
  21. return a>b?a:b;
  22. }
  23.  
  24. int main()
  25. {
  26. int t;
  27. cin>>t;
  28. int c=1;
  29. while(t--)
  30. {
  31. for(int i=0; i<3; i++)
  32. {
  33. cin>>node[i].s>>node[i].p;
  34. node[i].pri=1.0*node[i].s/(1.0*node[i].p);
  35. }
  36. int V;
  37. cin>>V;
  38. sort(node,node+3,cmp);
  39. long long ans=0;
  40. for(int i=0; i<node[0].s; i++)
  41. {
  42. for(int j=0; j<node[0].s; j++)
  43. {
  44. long long temp=i*node[1].s+j*node[2].s;
  45. if(temp>V)
  46. break;
  47. else
  48. {
  49. long long v=V-temp;
  50. ans=llmax(ans,v/node[0].s*node[0].p+i*node[1].p+j*node[2].p);
  51. }
  52. }
  53. }
  54. cout<<"Case "<<c++<<": "<<ans<<endl;
  55. }
  56. return 0;
  57. }

[2012山东ACM省赛] Pick apples (贪心,全然背包,枚举)的更多相关文章

  1. [2012山东ACM省赛] Pick apples (贪心,完全背包,枚举)

    Pick apples Time Limit: 1000MS Memory limit: 165536K 题目描述 Once ago, there is a mystery yard which on ...

  2. 10年省赛-Greatest Number (二分+暴力) + 12年省赛-Pick apples(DP) + UVA 12325(暴力-2次枚举)

    题意:给你n个数,在里面取4个数,可以重复取数,使和不超过M,求能得到的最大的数是多少: 思路:比赛时,和之前的一个题目很像,一直以为是体积为4(最多选择四次)的完全背包,结果并不是,两两求和,然后二 ...

  3. 山东ACM省赛历届入口

    山东省第一届ACM大学生程序设计竞赛 山东省第二届ACM大学生程序设计竞赛 山东省第三届ACM大学生程序设计竞赛 山东省第四届ACM大学生程序设计竞赛 山东省第五届ACM大学生程序设计竞赛 山东省第六 ...

  4. [2011山东ACM省赛] Sequence (动态规划)

    Sequence Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 Given an integer number sequence ...

  5. [2011山东ACM省赛] Identifiers(模拟)

    Identifiers Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描写叙述  Identifier is an important ...

  6. [2013山东ACM]省赛 The number of steps (可能DP,数学期望)

    The number of steps nid=24#time" style="padding-bottom:0px; margin:0px; padding-left:0px; ...

  7. [2011山东ACM省赛] Mathman Bank(模拟题)

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/sr19930829/article/details/24187925 Mathman Bank ni ...

  8. [2011山东ACM省赛] Binomial Coeffcients(求组合数)

    Binomial Coeffcients nid=24#time" style="padding-bottom:0px; margin:0px; padding-left:0px; ...

  9. 第八届山东ACM省赛F题-quadratic equation

    这个题困扰了我长达1年多,终于在今天下午用两个小时理清楚啦 要注意的有以下几点: 1.a=b=c=0时 因为x有无穷种答案,所以不对 2.注意精度问题 3.b^2-4ac<0时也算对 Probl ...

随机推荐

  1. 用Struts2实现列表显示和分页功能

    引用自http://www.2cto.com/kf/201309/243730.html BlogDAO.java文件 /** 根据条件(默认一张表所有数据)返回多条记录 */ public List ...

  2. 分享到xxx

    来源百度 一.概述 百度分享代码已升级到2.0,本页将介绍新版百度分享的安装配置方法,请点击左侧列表查看相关章节. 二.代码结构 分享代码可以分为三个部分:HTML.设置和js加载,示例如下: 代码结 ...

  3. <Android 基础(二十六)> 渐变色圆角Button

    简介 总结下之前看的自定义View的内容,结合一个简单的例子,阐述下基本用法和大致的使用流程,这个例子比较简单,更复杂的自定义View,随着自己的学习,后面再慢慢添加.作为一个Android开发者,这 ...

  4. 各浏览器禁用某网站JS脚本的方法 【转】

    某些网站,经常会加载一些非常讨厌的JS脚本,如果我们想禁止这个网站的JS脚本,可以使用下面的方法: 一.IE浏览器 1.在Internet选项中,选择安全选项卡,然后点击受限制的站点,点击下面的站点 ...

  5. 分享一个oracle 完整备份的批处理文件

    该批处理是基本可以无限针对使用window 服务器的oracle 备份,如下: set mydate=%DATE:~0,10% exp e_cards2016/e_cards2016@orcl ful ...

  6. c#实现内存映射文件共享内存

    原文:http://blog.csdn.net/wangtiewei/article/details/51112668 内存映射文件是利用虚拟内存把文件映射到进程的地址空间中去,在此之后进程操作文件, ...

  7. Object、String、数组的 toString() 方法和 equals() 方法及java.util.Arrays

    public class Test { public static void main(String[] args) { int[] a = {1, 2, 4, 6}; int[] b = a; in ...

  8. WinForm自定义控件

        [ToolboxBitmap(typeof(PropertyGrid))]//设置在工具箱中显示的小图标 public partial class ServiceManage : UserCo ...

  9. https的网站用了百度分享后网站在浏览器中不安全解决方法

    本文出至:新太潮流网络博客 一.先下载百度分享需要的所有东西 下载地址:http://pan.baidu.com/s/1boM7N8V 二.打开百度分享,获取到分享的代码 三.将下载好的百度分享需要的 ...

  10. wxpython 编程触发菜单或按钮事件

    最近逐步熟悉wxpython,编写了几个小小功能的GUI程序,GUI中免不了会有在代码中触发控件事件的业务需求.在其他Gui界面的语言中有postevent.triggerevent 调用事件名称的函 ...