• hud 4415 Assassin’s Creed


    呼,终于对了,真是太粗心了。。。。。。

    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 ;
    }
  • 相关阅读:
    BZOJ 2005 能量采集
    HDU 2841 Visible Trees(莫比乌斯反演)
    hihocoder 1543
    hihocoder 1311
    hdu 6069
    hdu 6058
    hdu 6034
    拓展欧几里得
    poj 3321
    树状数组总结
  • 原文地址:https://www.cnblogs.com/misty1/p/2702140.html
Copyright © 2020-2023  润新知