zoukankan      html  css  js  c++  java
  • hdu 4415 Assassin’s Creed 夜

    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;
    }
    
    
  • 相关阅读:
    【转】HBase中的时间维度
    【转】HBase基本原理
    【转】BloomFilter——大规模数据处理利器
    【转】HBase客户端API:管理特性
    es6 模本字符串拼接方法 ``
    Electron桌面应用打包流程
    vue-electron脚手架安装及说明 打包基于Vue的 桌面应用程序
    safari打开的页面数字识别变为蓝色
    使用jquery中$.each()方法来循环一个数据列表
    jquery实现点击控制div的显示和隐藏
  • 原文地址:https://www.cnblogs.com/liulangye/p/2702003.html
Copyright © 2011-2022 走看看