• 【题解】P4025 [PA2014]Bohater


    题目

    很清奇的贪心策略题

    主要是将所有的怪分成两种——$ d<a $的刷分回血怪和 $ d > a$ 的让人残血的BOSS

    我们分开处理,先把所有的的刷分怪打完,这样血达到最厚,再去打BOSS

    刷分怪先打血少的,也就是按d升序

    BOSS先打血药大的,也就是按a降序,这里很神奇

    详见代码

    code

    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<string>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    #define ci cosnt int &
    using namespace std;
    const int maxn = 100010;
    int n, d, a, tot, top;
    ll blood;
    struct Blood{
    	int d, a, del, id;
    }add[maxn], lss[maxn];
    
    bool cmp1(Blood a, Blood b){
    //不要想着多加血,要防止打怪时死 ,下面这样写就不对咯 
    //	return a.del > b.del;
    
    //以下为正解贪心策略----------------------------------------- 
    //对于刷分怪,要防止打怪的时候死掉
    //在不断的刷分当中,会一直加血,越往后血越多,应对刷分怪时能掉的血也越多    
    //全部刷完分后再去打会残血的BOSS,所以刷分怪的顺序只对刷分怪有影响,对BOSS无影响 
    	return a.d < b.d;
    }
    bool cmp2(Blood a, Blood b){
    //又是错误的写法哦 
    //	return a.d > b.d;//当然先打掉血多的 
    
    //残血怪,持续掉血, 
    
    //以下为正解------------------------------------------ 
    //倒着考虑,我们有一个最后的血量lastblood,打完刷分怪后得到的血量是maxblood,
    //全程回放,回放一个BOSS相当于吐出血药,收回残掉的血,也就是lastblood-=a,lastblood+=d,
    //这是一个加血的过程,全部回放完时,lastblood就回到了maxblood。
    //我们要保证回放的过程中的最优,贪心策略同cmp1,即a.a < b.a,
    //那么正过来看,排序策略就是a.a > b.a 。 
    	return a.a > b.a;
    }
    int main(){
    	scanf("%d%d",&n,&blood);
    	for(int i=1;i<=n;i++){
    		scanf("%d%d",&d,&a);
    		if(d > a){
    			lss[++tot].a = a;
    			lss[tot].d = d;
    			lss[tot].del = a - d;
    			lss[tot].id = i;
    		}
    		else{
    			add[++top].a = a;
    			add[top].d = d;
    			add[top].del = a - d;
    			add[top].id = i;
    		}
    	}
    	sort(add + 1, add + 1 + top, cmp1);
    	sort(lss + 1, lss + 1 + tot, cmp2);
        if(blood <= 0){
    		printf("NIE
    ");
    		return 0;
    	}
    	for(int i = 1; i <= top; i++){
    		if(blood - add[i].d <= 0){
    			printf("NIE
    ");
    			return 0;
    		}
    		blood += add[i].del;
    	}
    	for(int i = 1; i <= tot; i++){
    		if(blood - lss[i].d <= 0){
    			printf("NIE
    ");
    			return 0;
    		}
    		blood += lss[i].del; 
    	}
    	printf("TAK
    ");
    	for(int i = 1; i <= top; i++){
    		printf("%d ",add[i].id);
    	} 
    	for(int i = 1; i <= tot; i++){
    		printf("%d ",lss[i].id);
    	}
    	printf("
    ");
    	return 0;
    }
    
    
  • 相关阅读:
    4Windows程序设计 文本输出
    Dapr牵手.NET学习笔记:可观测性分布式跟踪
    Dapr牵手.NET学习笔记:Actor小试
    Dapr牵手.NET学习笔记:绑定
    Dapr牵手.NET学习笔记:发布订阅
    jenkins修改默认的工作空间
    Jenkins自动化编译部署vue项目至远程服务器
    Linux系统下安装Nginx,并反向代理运行vue项目
    Jenkins构建打包vue项目后丢失静态资源文件
    Jenkins修改显示语言为中文
  • 原文地址:https://www.cnblogs.com/ZhengkunJia/p/13282909.html
Copyright © 2020-2023  润新知