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。

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

代码:

/*
* @author FreeWifi_novicer
* language : C++/C
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<queue> using namespace std; #define clr( x , y ) memset(x,y,sizeof(x))
#define cls( x ) memset(x,0,sizeof(x))
#define mp make_pair
#define pb push_back
typedef long long lint;
typedef long long ll;
typedef long long LL; /*Nothing is true , everything is permitted*/ const int maxn = 1e5 + 100 ;
lint n , m ;
lint kill_e1 , cost1 ;
lint ans_cost , ans_kill ;
lint e1[maxn] ; struct em{
lint cos , kil ;
}e2[maxn] ; bool cmp( em a , em b ){
return a.cos < b.cos ;
} void only_kill_e1( int len1 ){
lint dur = m ;
cost1 = 0 ;
kill_e1 = 0 ;
int k = 0 ;
while( k < len1 && dur >= e1[k] ){
cost1 += e1[k] ;
kill_e1 ++ ;
dur -= e1[k++] ;
}
} bool kill_all_e2( int len2 , int len1 ){
if( !len2 )
return false ;
lint dur = m ;
if( e2[0].cos > dur )
return false ;
dur -= e2[0].cos ;
lint sumb = 0 ;
for( int i = 0 ; i < len2 ; i++ )
sumb += e2[i].kil ;
lint rest = sumb - len2 + 1 ;
if( rest >= len1 ){//假设多余的sword能够解决掉全部b = 0的敌人,则可解决全部敌人
ans_cost = e2[0].cos ;
ans_kill = n ;
return true ;
}
else{
int i = 0 , j = 1 ; //比較e2[j].cos 与 e1[i]的大小,选择消耗耐久度小的去杀
lint tmp = len1 - rest ;
ans_cost = e2[0].cos ;
ans_kill = len2 + rest ;
while( i < tmp ){
if( dur < e1[i] && dur < e2[j].cos ) break ;
if( j < len2 && e2[j].cos <= e1[i] ){
ans_cost += e2[j].cos ;
dur -= e2[j].cos ;
tmp-- ; j++ ;
}
else{
ans_cost += e1[i] ;
dur -= e1[i] ;
i++ ;
}
ans_kill ++ ;
}
return true ;
}
}
int main(){
// freopen("input.txt","r",stdin);
int t ; cin >> t ; int kase = 1 ;
while( t-- ){
cin >> n >> m ;
ans_kill = kill_e1 = 0 ;
ans_cost = cost1 = 0 ;
lint len1 = 0 , len2 = 0 ;
for( int i = 1 ; i <= n ; i++ ){
lint a , b ;
scanf( "%I64d%I64d" , &a , &b ) ;
if( !b ){
e1[len1++] = a ;
}
else{
e2[len2].cos = a ;
e2[len2++].kil = b ;
}
}
printf( "Case %d: " , kase++ ) ;
sort( e1 , e1 + len1 ) ;
sort( e2 , e2 + len2 , cmp ) ; only_kill_e1( len1 ) ; if( !kill_all_e2( len2 , len1 ) ){
printf( "%I64d %I64d\n" , kill_e1 , cost1 ) ;
continue ;
}
if( ans_kill > kill_e1 ){
printf( "%I64d %I64d\n" , ans_kill , ans_cost ) ;
}
else{
if( ans_kill == kill_e1 )
printf( "%I64d %I64d\n" , ans_kill , min( ans_cost , cost1 ) ) ;
else
printf( "%I64d %I64d\n" , kill_e1 , cost1 ) ;
}
}
return 0;
}

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. unix关于打包命令zip的使用

    unix zip命令的基本使用方法是: zip [參数] [打包后的文件名称] [打包的文件夹路径] linux zip命令參数列表: -a 将文件转成ASCII模式 -F 尝试修复损坏的压缩文件 - ...

  2. 路由器一键桥接Android实现

    開始之前,首先说一下什么叫一键桥接,所谓一键桥接,就是点击一下.就能够对所连接的路由器进行网络中继设置.以实现路由器能够通过已有的无线路由器进行网络訪问. 那么实现这个功能有几种方法呢?能够说有非常多 ...

  3. jQuery动画animate()的使用

    自己定义动画效果: 使用方法:animate(js对象,运行时间.回调函数): js对象:{ }描写叙述动画运行之后元素的样式 运行时间:毫秒数 回调函数:动画运行结束后要运行的函数 html代码: ...

  4. [C#] 怎样分析stackoverflow等clr错误

    有时候由于无限递归调用等代码错误,w3wp.exe会报错退出.原因是clr.exe出错了. 这样的错误比較难分析,由于C#代码抓不住StackOverflowException等异常. 处理方法是:生 ...

  5. malloc和new出来的地址都是虚拟地址 你就说内存管理单元怎么可能让你直接操作硬件内存地址!

    malloc的实现与物理内存自然是无关的,内核为每个进程维护一张页表,页表存储进程空间内每页的虚拟地址,页表项中有的虚拟内存页对应着某个物理内存页面,也有的虚拟内存页没有实际的物理页面对应.无论mal ...

  6. ROS-SLAM-gmapping

    前言:gmapping是最常用和成熟的slam导航算法,gmapping功能包集成了Rao-Blackwellized粒子滤波算法,为开发者隐去了复杂的内部实现. 前提:已下载并编译了相关功能包集,如 ...

  7. jquery中$each()

    $.each():可用于遍历任何的集合(无论是数组或对象) $(selector).each():专用于jquery对象的遍历, 如果是数组,回调函数每次传入数组的索引和对应的值(值亦可以通过this ...

  8. tp5控制器调用,方法调用

      <?php //命名空间 namespace app\index\controller; use app\admin\controller\Deer; class User{ public ...

  9. JavaScript设计模式学习——builder pattern(建造者模式)

    个人理解的应用场景 举个例子,比如想要创建各种类型的车的实例,车的类型有很多种,但创建每种类型车的接口定义可能是一样的,就用到了此模式 相关概念的通俗解释 上述例子中接口的定义叫builder 接口到 ...

  10. SQL Server死锁排查

    1. 死锁原理 根据操作系统中的定义:死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所站用不会释放的资源而处于的一种永久等待状态. 死锁的四个必要条件:互斥条件(Mutua ...