pid=4415">HDU 4415

题意:

壮哉我Assassin!

E叔有一柄耐久度为m的袖剑,以及n个目标士兵要去解决。

每解决掉一个士兵,消耗袖剑Ai的耐久度。且获得该士兵的武器,能够使用该武器解决Bi名其它士兵。

E叔要尽可能地消耗更少耐久度解决很多其它的敌人,求最小消耗与最大杀敌数。

思路:

我们把士兵分为两个集合:e1与e2。e1的士兵 Bi = 0 。 e2 的 Bi > 0.

我们发现。假设能解决e2的随意一个,e2就可以全灭,那么我们对e2依据消耗进行升序排序,消灭e2集合的消耗即为排序后的第一个士兵的Ai。

其次。要尽可能多地解决e1的士兵,则相同对e1依据消耗进行升序排序,杀到耐久度小于下一士兵Ai为止;

乍一看,最优解就是先全灭e2再用剩下的耐久度消灭e1较小Ai的敌人,用e2剩下的Bi消耗e1较大Ai的敌人;

假设不能全灭e2,则用全部耐久度去解决e1的敌人。

这样做的确非常优了。但还不是最优。考虑这组例子:

1

4 5

2 1

3 1

5 0

100 0

依照刚才的贪心策略,先解决Bi > 0 的前两个士兵(用袖剑杀死士兵1,用士兵1的武器杀死士兵2),消耗2耐久度。然后用士兵2的武器解决Ai最大的士兵4。士兵3由于耐久度不够则无法解决,答案是3 2。

可是我们能够先用袖剑杀死士兵1与士兵2。用这两个士兵的武器去解决士兵3,4,明显最优解为4 5。

于是我们对之前贪心策略做出改进:

设用袖剑杀死一个 Bi = 0 的士兵1消耗为a。设用士兵武器杀死一个在 Bi > 0 的集合里的士兵2。士兵2的最小消耗为b;

假设a < b,则用袖剑解决士兵1,用士兵武器解决士兵2;

否则。则用袖剑解决士兵2。保留士兵武器解决更大消耗的士兵(可能是士兵1)。

换而言之。就是E叔面对一个 Bi > 0 的士兵,他说:本来准备用士兵武器杀死你。如今我又不想了,我要用袖剑杀死你,由于你的消耗并不大,我要换回用以杀死你的士兵武器。去杀死消耗更大的敌人。

可能叙述还是有点不清。

。这个贪心策略看起来极其像dp,然而它真心不是dp。

。以后思路更清晰的时候再改改吧~

代码:

  1. /*
  2. * @author FreeWifi_novicer
  3. * language : C++/C
  4. */
  5. #include<cstdio>
  6. #include<iostream>
  7. #include<cstring>
  8. #include<cstdlib>
  9. #include<cmath>
  10. #include<algorithm>
  11. #include<string>
  12. #include<map>
  13. #include<set>
  14. #include<vector>
  15. #include<queue>
  16. using namespace std;
  17. #define clr( x , y ) memset(x,y,sizeof(x))
  18. #define cls( x ) memset(x,0,sizeof(x))
  19. #define mp make_pair
  20. #define pb push_back
  21. typedef long long lint;
  22. typedef long long ll;
  23. typedef long long LL;
  24. /*Nothing is true , everything is permitted*/
  25. const int maxn = 1e5 + 100 ;
  26. lint n , m ;
  27. lint kill_e1 , cost1 ;
  28. lint ans_cost , ans_kill ;
  29. lint e1[maxn] ;
  30. struct em{
  31. lint cos , kil ;
  32. }e2[maxn] ;
  33. bool cmp( em a , em b ){
  34. return a.cos < b.cos ;
  35. }
  36. void only_kill_e1( int len1 ){
  37. lint dur = m ;
  38. cost1 = 0 ;
  39. kill_e1 = 0 ;
  40. int k = 0 ;
  41. while( k < len1 && dur >= e1[k] ){
  42. cost1 += e1[k] ;
  43. kill_e1 ++ ;
  44. dur -= e1[k++] ;
  45. }
  46. }
  47. bool kill_all_e2( int len2 , int len1 ){
  48. if( !len2 )
  49. return false ;
  50. lint dur = m ;
  51. if( e2[0].cos > dur )
  52. return false ;
  53. dur -= e2[0].cos ;
  54. lint sumb = 0 ;
  55. for( int i = 0 ; i < len2 ; i++ )
  56. sumb += e2[i].kil ;
  57. lint rest = sumb - len2 + 1 ;
  58. if( rest >= len1 ){//假设多余的sword能够解决掉全部b = 0的敌人,则可解决全部敌人
  59. ans_cost = e2[0].cos ;
  60. ans_kill = n ;
  61. return true ;
  62. }
  63. else{
  64. int i = 0 , j = 1 ; //比較e2[j].cos 与 e1[i]的大小,选择消耗耐久度小的去杀
  65. lint tmp = len1 - rest ;
  66. ans_cost = e2[0].cos ;
  67. ans_kill = len2 + rest ;
  68. while( i < tmp ){
  69. if( dur < e1[i] && dur < e2[j].cos ) break ;
  70. if( j < len2 && e2[j].cos <= e1[i] ){
  71. ans_cost += e2[j].cos ;
  72. dur -= e2[j].cos ;
  73. tmp-- ; j++ ;
  74. }
  75. else{
  76. ans_cost += e1[i] ;
  77. dur -= e1[i] ;
  78. i++ ;
  79. }
  80. ans_kill ++ ;
  81. }
  82. return true ;
  83. }
  84. }
  85. int main(){
  86. // freopen("input.txt","r",stdin);
  87. int t ; cin >> t ; int kase = 1 ;
  88. while( t-- ){
  89. cin >> n >> m ;
  90. ans_kill = kill_e1 = 0 ;
  91. ans_cost = cost1 = 0 ;
  92. lint len1 = 0 , len2 = 0 ;
  93. for( int i = 1 ; i <= n ; i++ ){
  94. lint a , b ;
  95. scanf( "%I64d%I64d" , &a , &b ) ;
  96. if( !b ){
  97. e1[len1++] = a ;
  98. }
  99. else{
  100. e2[len2].cos = a ;
  101. e2[len2++].kil = b ;
  102. }
  103. }
  104. printf( "Case %d: " , kase++ ) ;
  105. sort( e1 , e1 + len1 ) ;
  106. sort( e2 , e2 + len2 , cmp ) ;
  107. only_kill_e1( len1 ) ;
  108. if( !kill_all_e2( len2 , len1 ) ){
  109. printf( "%I64d %I64d\n" , kill_e1 , cost1 ) ;
  110. continue ;
  111. }
  112. if( ans_kill > kill_e1 ){
  113. printf( "%I64d %I64d\n" , ans_kill , ans_cost ) ;
  114. }
  115. else{
  116. if( ans_kill == kill_e1 )
  117. printf( "%I64d %I64d\n" , ans_kill , min( ans_cost , cost1 ) ) ;
  118. else
  119. printf( "%I64d %I64d\n" , kill_e1 , cost1 ) ;
  120. }
  121. }
  122. return 0;
  123. }

HDU 4415 Assassin&#39;s Creed(贪心)的更多相关文章

  1. HDU 4415 - Assassin’s Creed

    Problem Description Ezio Auditore is a great master as an assassin. Now he has prowled in the enemie ...

  2. HDU-4415 Assassin’s Creed 贪心

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4415 用贪心来解,开始分为两个集合的方法错了,没有考虑之间的相互影响,正确的姿势应该是这样的,分两种情 ...

  3. HDU 5371 Hotaru&#39;s problem(Manacher算法+贪心)

    manacher算法详见 http://blog.csdn.net/u014664226/article/details/47428293 题意:给一个序列,让求其最大子序列,这个子序列由三段组成, ...

  4. hdu 1257 最少拦截系统(简单贪心)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1257 虽然分类是dp感觉还是贪心 比较水 #include <iostream> #inclu ...

  5. HDU 5783 Divide the Sequence (贪心)

    Divide the Sequence 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5783 Description Alice has a seq ...

  6. HDU 5969 最大的位或 【贪心】 (2016年中国大学生程序设计竞赛(合肥))

    最大的位或 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem De ...

  7. POJ 1065 Wooden Sticks / hdu 1257 最少拦截系统 DP 贪心

    参考链接:http://blog.csdn.net/xiaohuan1991/article/details/6956629 (HDU 1257 解题思路一样就不继续讲解) POJ 1065题意:给你 ...

  8. HDU 4974 A simple water problem(贪心)

    HDU 4974 A simple water problem pid=4974" target="_blank" style="">题目链接 ...

  9. HDU 3177 Crixalis&#39;s Equipment(贪婪)

    主题链接:http://acm.hdu.edu.cn/showproblem.php? pid=3177 Problem Description Crixalis - Sand King used t ...

随机推荐

  1. Sereja and Bottles-水题有点坑爹

    CodeForces - 315A Sereja and Bottles Time Limit: 2000MS   Memory Limit: 262144KB   64bit IO Format:  ...

  2. 轻松学习JavaScript十二:JavaScript基于面向对象之创建对象(一)

    这一次我们深入的学习一下JavaScript面向对象技术,在学习之前,必要的说明一下一些面向对象的一些术语. 这也是全部面对对象语言所拥有的共同点.有这样几个面向对象术语: 对象 ECMA-262把对 ...

  3. hdoj 2795 Billboard 【线段树 单点更新 + 维护区间最大值】

    Billboard Time Limit: 20000/8000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  4. 浅析PHP中cookie与session技术

    1.cookie是什么? cookie指某些站点为了辨别用户身份.进行session跟踪而储存在用户本地终端上的数据(通常经过加密). 通俗来理解就是,你去一个专卖店或者超市买东西,然后店里给你办一张 ...

  5. 42.写入XML

    #include <QtGui> #include <QtXml> #include <iostream> //创建一个树结构 void populateTree( ...

  6. 枚举所有排列-STL中的next_permutation

    枚举排列的常见方法有两种 一种是递归枚举 另一种是STL中的next_permutation //枚举所有排列的另一种方法就是从字典序最小排列开始,不停的调用"求下一个排列"的过程 ...

  7. Oracle 复合索引设计原理——前缀性和可选性

    前缀性: 复合索引的前缀性是指只有当复合索引的第一个字段出现在SQL语句的谓词条件中时,该索引才会被用到.如复合索引为(ename,job,mgr),只要谓词条件中出现第一个字段ename,就可以用复 ...

  8. php.ini配置文件参数优化

    用于生产环境中的PHP需要对其进行优化,让PHP自身发挥更好的性能,除了写好PHP代码,还要配置好php-fpm以及php.ini调优.本文从内存.OPcache.上传.会话以及安全等方面讲解php. ...

  9. javascript动画函数封装(升级版)

    //把 任意对象 的 任意数值属性 改变为 任意的目标值 function animate(obj, json, fn) { clearInterval(obj.timer); obj.timer = ...

  10. ECMAScript prototype的一个疑问。

    既然是疑问 当然首先要贴一段代码. 背景: 探究js的原型继承模式. 疑惑:为何person1和person2的prototype 居然是相等的. 附: 1.Object.create(proto, ...