poj 1042 gone fishing

题目要求:

   由有n个湖, 按照顺序排列,一个人从第一个湖向最后一个湖行进(方向只能从湖0到湖n-1),途中可以在湖中钓鱼。在每个湖中钓鱼时,开始的5分钟内可以钓到 f[i] 条,之后每5分钟钓到的鱼数目递减 d[i] ,且每两个相邻的湖的距离 t[i] 给出(t[i] 表示 由第 i 个湖向第 i + 1个湖行进在路上花费5分钟的倍数的时间, 即如果t[3] = 4,则表示从第三个湖向第四个湖行进需要花费20分钟)。 现给定总时间h 小时,求出在每个湖钓鱼时间的最好的方案,使得钓鱼的总数最多,如果两种方案结果相同,则输出在较小序号的湖中钓鱼时间更多的那个。

题目分析:

  最优化问题,可以选择动态规划或者贪心算法,初看起来,是个多阶段的决策问题,且每个阶段会对下一个阶段产生影响,并不好找到合适的贪心策略,更适合采用动态规划。先考虑动态规划算法,可以考虑 动规数组 dp[t][n] 表示在 t 时刻到达湖 n 时之前钓鱼结果的最优值,可以找出递推关系式 dp[t][n] =  max{ dp[t1][n-1] + fish_result(n-1, t - t1 - t[n-1])}

即对到达湖 n - 1的时刻 t1 进行枚举(在一定的范围之内,小于 t - t[n-1], 大于xx),然后取出最大值作为 dp[t][n],这样从 n - 1 推到 n。

  个人认为这种动态规划的方法是可行的,但是。。由于水平太菜。。没有成功。。

  考虑采用贪心的算法来实现,仔细分析一下,当确定了需要到达的湖的个数n,也就确定了在路上需要消耗的时间,从而得到钓鱼的总时间,这样在规定的时间内钓鱼,每次都选择当前5分钟内收益最大的那个湖进行钓鱼(可以采用优先级队列  priority_queue 来实现)。 考虑到这样做会有可能出现先在湖 A 中钓鱼,再在湖B中钓鱼,然后再回到湖A中钓鱼... 但是这样不会影响最终的结果(这也是贪心算法可以运用到此题的前提)。因为,虽然只能从湖0到湖n-1行进,此时进行贪心选择虽然每次选择的顺序可能不断颠倒变化,但是这只是确定湖A有几次被选中钓鱼,也就是确定从湖0到湖n-1每个湖中钓鱼的时间。在实际行进途中钓鱼的时候,就按照贪心算出来的方案(在湖 i 中钓鱼几次),在途中的湖中钓鱼。

  通过固定要经过的湖的个数n,将每个湖由于在路上消耗时间的差异去掉,使得面临的选择无差异,可以运用贪心算法。

实现代码:

  1. #include<iostream>
  2. #include<stdio.h>
  3. #include<string.h>
  4. #include<queue>
  5. #include<vector>
  6. using namespace std;
  7. #define MAX_INTERVAL_NUM 200
  8. #define MAX_LAKE_NUM 25
  9.  
  10. int dist_time[MAX_LAKE_NUM];
  11. int min_dist_time[MAX_LAKE_NUM];
  12. int stay_times[MAX_LAKE_NUM];
  13. int init_num[MAX_LAKE_NUM];
  14. int dec_num[MAX_LAKE_NUM];
  15.  
  16. struct LakeNode{
  17. int lake_index;
  18. int cur_fish_amount;
  19. int dec_amount;
  20. int stay_time;
  21. };
  22. LakeNode lake_nodes[MAX_LAKE_NUM];
  23. struct cmp{
  24. bool operator() (LakeNode* lake1, LakeNode* lake2){
  25. if (lake1->cur_fish_amount == lake2->cur_fish_amount){
  26. return lake1->lake_index > lake2->lake_index;
  27. }
  28. return lake1->cur_fish_amount < lake2->cur_fish_amount;
  29. }
  30. };
  31.  
  32. void ClearQueue(priority_queue<LakeNode*, vector<LakeNode*>, cmp>& queue){
  33. while(! queue.empty()){
  34. queue.pop();
  35. }
  36. }
  37.  
  38. int Resolve(int N, int T){
  39. priority_queue<LakeNode*, vector<LakeNode*>, cmp> lake_queue;
  40. LakeNode* lake;
  41. int result = 0, max_amount = 0;
  42. stay_times[0] = T;
  43. for (int n = 1; n <= N; n ++){
  44. result = 0;
  45. int fish_time = T - min_dist_time[n - 1];
  46. if (fish_time <= 0){
  47. break;
  48. }
  49. ClearQueue(lake_queue);
  50. for(int i = 0; i < n; i ++){
  51. lake_nodes[i].stay_time = 0;
  52. lake_nodes[i].lake_index = i;
  53. lake_nodes[i].cur_fish_amount = init_num[i];
  54. lake_nodes[i].dec_amount = dec_num[i];
  55.  
  56. lake_queue.push((LakeNode*)&lake_nodes[i]);
  57. }
  58. while(! lake_queue.empty() && fish_time > 0){
  59. lake = lake_queue.top();
  60. lake_queue.pop();
  61.  
  62. if (lake->cur_fish_amount > 0){
  63. result += lake->cur_fish_amount;
  64. lake->cur_fish_amount -= lake->dec_amount;
  65. }
  66. if (lake->cur_fish_amount <= 0){
  67. lake->cur_fish_amount = 0;
  68. }
  69.  
  70. lake->stay_time ++;
  71. fish_time --;
  72. lake_queue.push(lake);
  73.  
  74. }
  75. if (result > max_amount){
  76. max_amount = result;
  77. for(int i = 0; i < n; i ++){
  78. stay_times[i] = lake_nodes[i].stay_time;
  79. }
  80. }
  81. }
  82. return max_amount;
  83. }
  84.  
  85. int main(){
  86. int n, h;
  87.  
  88. while(true){
  89. cin >> n;
  90. if (n == 0){
  91. break;
  92. }
  93. cin >> h;
  94. h = h*12;
  95. for(int i = 0; i < n ; i ++){
  96. cin >> init_num[i];
  97. stay_times[i] = 0;
  98. }
  99. for(int i = 0; i < n; i ++){
  100. cin >> dec_num[i];
  101. }
  102. min_dist_time[0] = 0;
  103. cin >> dist_time[0];
  104. for(int i = 1; i < n - 1; i ++){
  105. cin >> dist_time[i];
  106. min_dist_time[i] = min_dist_time[i - 1] + dist_time[i-1];
  107. }
  108. min_dist_time[n-1] = min_dist_time[n-2] + dist_time[n-2];
  109.  
  110. int result = Resolve(n, h);
  111. cout << stay_times[0]*5 ;
  112. for(int i = 1; i < n; i ++){
  113. cout << ", " << stay_times[i]*5;
  114. }
  115. cout << endl << "Number of fish expected: " << result << endl << endl;
  116. }
  117. return 0;
  118. }

poj_1042 贪心算法的更多相关文章

  1. 贪心算法(Greedy Algorithm)

    参考: 五大常用算法之三:贪心算法 算法系列:贪心算法 贪心算法详解 从零开始学贪心算法 一.基本概念: 所谓贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择.也就是说,不从整体最优上加以 ...

  2. 算法导论----贪心算法,删除k个数,使剩下的数字最小

    先贴问题: 1个n位正整数a,删去其中的k位,得到一个新的正整数b,设计一个贪心算法,对给定的a和k得到最小的b: 一.我的想法:先看例子:a=5476579228:去掉4位,则位数n=10,k=4, ...

  3. LEETCODE —— Best Time to Buy and Sell Stock II [贪心算法]

    Best Time to Buy and Sell Stock II Say you have an array for which the ith element is the price of a ...

  4. ACM_ICPC hdu-2111(简单贪心算法)

    一道非常简单的贪心算法,但是要注意输入的价值是单位体积的价值,并不是这个物品的总价值!#include <iostream> #include <stdio.h> #inclu ...

  5. 基于贪心算法的几类区间覆盖问题 nyoj 12喷水装置(二) nyoj 14会场安排问题

    1)区间完全覆盖问题 问题描述:给定一个长度为m的区间,再给出n条线段的起点和终点(注意这里是闭区间),求最少使用多少条线段可以将整个区间完全覆盖 样例: 区间长度8,可选的覆盖线段[2,6],[1, ...

  6. 增强学习贪心算法与Softmax算法

    (一) 这个算法是基于一个概率来对探索和利用进行折中:每次尝试时,以概率进行探索,即以均匀概率随机选取一个摇臂,以的概率进行利用,即以这个概率选择当前平均奖赏最高的摇臂(如有多个,则随机选取). 其中 ...

  7. 【九度OJ】题目1434贪心算法

    题目 本题的贪心算法策略需要深入思考一下 看到题目,最初没有理解题目的要求:看尽量多的完整的节目.尽量多是指数量多,自己理解成观看的时间最长.这样想其实简化了这道题. 正确理解题意后,首先想到的想法是 ...

  8. 题目1437:To Fill or Not to Fill:贪心算法解决加油站选择问题(未解决)

    //贪心算法解决加油站选择问题 //# include<iostream> # include<stdio.h> using namespace std; # include& ...

  9. 贪心算法(Greedy Algorithm)之最小生成树 克鲁斯卡尔算法(Kruskal&#39;s algorithm)

    克鲁斯卡尔算法(Kruskal's algorithm)是两个经典的最小生成树算法的较为简单理解的一个.这里面充分体现了贪心算法的精髓.大致的流程能够用一个图来表示.这里的图的选择借用了Wikiped ...

随机推荐

  1. mybaits if标签语句

    Mybatis if 标签可用在许多类型的 SQL 语句中,我们以查询为例.首先看一个很普通的查询: <!-- 查询用户列表,like用户名称 --> <select id=&quo ...

  2. Lua------------------改善Unity编辑器对Lua文件的支持

    原创 2017年03月10日 18:44:22 标签: Unity / lua / 编辑器 952 当前版本的Unity(截至Unity5.5.x)中TextAsset类不支持后缀为lua的文件,将l ...

  3. 7月目标 socket , 一致性哈希算法 ; mongodb分片; 分布式消息队列; 中间件的使用场景

      分布式的基础:一致性哈希  路由算法的一致性hash http://www.jiacheo.org/blog/174 http://www.tuicool.com/articles/vQVbmai ...

  4. Enhance基本例子

    太晚了,有些东西没有补充,回头再补上. 先上Demo 1.要执行的方法 package enhancerTest; /** * Created by LiuSuSu on 2017/3/26. */ ...

  5. CentOS系统很卡的基本排查方法

    来源:http://www.centoscn.com/CentOS/Intermediate/2017/1012/9032.html 一. 查看内存使用情况  1. free命令可查看内存使用情况 2 ...

  6. docker默认ip查询

    查询docker ip地址 docker-machine ip default

  7. js 历史

    原文http://javascript.ruanyifeng.com/introduction/history.html JavaScript的诞生 JavaScript 因为互联网而生,紧随着浏览器 ...

  8. Thinkphp5 Route用法

    域名路由:domain 1.application/router.php 文件位置,吧一下代码放进去就可以了 use think\Route; Route::domain('app.tp5a.com' ...

  9. 续:纠正:ubuntu 【6.04 LTS】可以安装安装 ! for《Oracle-10.2.0.1,打补丁10.2.0.5:在 debian 版本4【不含4】以上,及 ubuntu 7.04【不含7.04】以上都可以安装!》

    经过长时间的试错.探索,终于查明无法顺利安装oracle10g的原因,并且找到顺利安装的方式. 要点: 无法安装的根本原因有2: 1:libc6-dev的版本为2.23-0ubuntu10,其中的cr ...

  10. perforce使用技巧

    如果用其他编辑器打开一个在perforce上的文件, 只需要在notepad++ (或者其他)上右键选择 然后到perforce的workspace里Ctrl + V 即可定位到该文件. 再使用Ctr ...