http://acm.hdu.edu.cn/showproblem.php?pid=4415

把原数据分两组 一组 B 为 0   另一组 B 不为 0

B 不为 0 的那组 要么不死 要么全死

对于 B 全死的情况 这一组里面的人 主角可以用自己的剑杀死 也可以用敌人的剑杀死

如果用自己的剑杀死 如果杀死一个人 一定是 A 最小的那一个 如果是两个人 一定是 A 最小的那两个

枚举  比较最优解

代码及其注释:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>

#define LL long long
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
const int N=100005;
struct node
{
    int a,b;
}mem[N];
int sum[N];//分组后 每组从最左边开始到第 i 个人 A的和
int num,cost;//最优 杀人数 和 花费
int n,m,L;//L 为分组 界限
bool cmpa(node x,node y)
{
    return x.a<y.a;
}
bool cmpb(node x,node y)
{
    return x.b<y.b;
}
int Search_B(int l,int r,int k)//二分查找第一组前几项和中最后一个小于等于 k 的位置
{
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(sum[mid]<=k)
        l=mid+1;
        else
        r=mid-1;
    }
    return r;
}
void Test(int num1,int cost1,int k)//对各种情况进行计算取舍
{
    int temp=min(k,L);
    num1+=temp;
    int w=Search_B(0,L-temp-1,m-cost1);
    if(w>=0)
    {
        cost1+=sum[w];
        num1+=(w+1);
    }
    if(num1>num||(num1==num&&cost1<cost))
    {num=num1;cost=cost1;}
}
int main()
{
    //freopen("data.txt","r",stdin);
    int T;
    scanf("%d",&T);
    for(int ca=1;ca<=T;++ca)
    {
        scanf("%d %d",&n,&m);
        for(int i=0;i<n;++i)
        scanf("%d %d",&mem[i].a,&mem[i].b);
        sort(mem,mem+n,cmpb);//先按B排序
        for(L=0;L<n;++L)
        {
            if(mem[L].b)//找到 第一个 B 不为 0 的位置
            break;
        }
        sort(mem,mem+L,cmpa);//将两组分别按 A 排序
        sort(mem+L,mem+n,cmpa);
        for(int i=0;i<L;++i)
        {
            sum[i]=mem[i].a;
            if(i>0)
            sum[i]+=sum[i-1];
        }
        int temp=0;
        for(int i=L;i<n;++i)
        {
            sum[i]=mem[i].a;
            if(i>L)
            sum[i]+=sum[i-1];
            temp+=mem[i].b;//累计第二组 B 的和
        }
        num=0;cost=0;
        Test(0,0,0);//是第二组 都不死的情况
        for(int i=1;i<=n-L;++i)
        {
            if(sum[L+i-1]<=m)//枚举 第二组有几个是主角直接杀死的
            Test(n-L,sum[L+i-1],temp-(n-L-i));
        }
        printf("Case %d: %d %d\n",ca,num,cost);
    }
    return 0;
}

 

posted on 2012-09-25 18:16  夜->  阅读(194)  评论(0编辑  收藏  举报