呼,终于对了,真是太粗心了。。。。。。
http://acm.hdu.edu.cn/showproblem.php?pid=4415
题意:一个人开始时有m个能量,他要杀死n个人,杀死每个人需要消耗能量为ai,杀死这个人后可以使用这个人的武器杀死bi个人,为怎样才能消耗最少的能量杀最多的人。
思路:贪心,比赛的时候根本没想用什么算法,只是按自己的想法写代码,怎么也不过,赛后问了一下队友,然后才觉得自己的想法还是有错误的。按队友的思路写了一个程序却怎么都是WA。最后发现原来是当Bi不为0的人都杀完后忘了加用武器杀死Bi为0的人的个数,呃,无奈啊。。
将n个人按Bi是否为0分别存在两个数组中,如果Bi不为0的数组有一个人能消耗能量杀死,那么所有不为0的人都能被杀死,然后处理Bi为0的人,在上一组中Bi未用完的可以继续杀死人,如果用完了,那就用能量来杀死,关键在于,Bi不为0的人除了第一个,其他人可以被武器杀死,也可以用能量杀死,如果他用能量杀死,那么武器就可以多杀死一个Bi为0 的人,所以在这一步就是比较Bi不为0的和Bi为0的那个消耗的能量更少了。还有一点,全部用能量杀死的人是否不通过武器消耗的能量多,这点要特殊判断。
呃,这题就是靠细心啊,考虑问题太不仔细了。。。。。。
代码:
View Code
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> #include <math.h> #define N 100005 using namespace std ; int a[N] , b[N] ; int s ; int main() { int cas , c , i ; int n , m , num , st , flag ; int numx , stx ; //freopen( "input.txt" , "r" , stdin ); scanf ( "%d" , &cas ); for ( c = 1 ; c <= cas ; c++ ) { scanf ( "%d%d" , &n , &m ) ; s = 0 ; int id1 = 0 , id2 = 0 ; for ( i = 0 ; i < n ; i++ ) { int x , y ; scanf ( "%d%d" , &x , &y ); s += y ;//所有Bi的和 if ( !y ) a[id1++] = x ;//Bi为0 else b[id2++] = x ;//Bi不为0 } int all = m ; if ( id1 )//对A、B数组排序 sort ( a , a + id1 ); if ( id2 ) sort ( b , b + id2 ); flag = 0 ; num = 0 ; st = 0 ; if ( b[0] <= m )//判断一下能否找到一个Bi不为0的开始点 { num = id2 ; m -= b[0] ; st = b[0] ; b[0] = -1 ; flag = 1 ; } if ( !flag )//如果找不到,那么就只能完全用能量 { for ( i = 0 ; i < id1 ; i++ ) if ( a[i] <= m ) { st += a[i] ; m -= a[i] ; num++ ; } else break ; } else { if ( s + 1 >= n )//否则,判断一下Bi的和是否可以不在消耗能量杀死所有的人 { num = n ; } else { int nx = id1 + id2 - s - 2 ;//如果不能的话,继续找能杀死的最多的人 num += ( s + 1 - id2 );//这里忘了加,WA了无数次啊 for ( i = 0 ; i <= nx ; i++ ) b[id2++] = a[i] ; sort ( b , b + id2 ); for ( i = 1 ; i < id2 ; i++ ) { if ( num >= n ) break ; if ( b[i] <= m ) { num++ ; m -= b[i] ; st += b[i] ; } else break ; } } } //判读一下仅用能量杀死的人数 stx = 0 ; numx = 0 ; for ( i = 0 ; i < id1 ; i++ ) { if( numx >= n ) break ; if ( a[i] <= all ) { numx++ ; all -= a[i] ; stx += a[i] ; } else break ; } printf ( "Case %d: " , c ); if ( numx > num || ( numx == num && stx < st )) printf ( "%d %d\n" , numx , stx ); else printf ( "%d %d\n" , num , st ); } return 0 ; }