• bzoj3709: [PA2014]Bohater 贪心


    ~~~题面~~~

    题解:

      首先有一个比较明显的策略,肯定先要把能带给自己受益的先选完,然后再以最佳状态去打那些会给自己带来损失的怪。

      对于前一部分(可以带来受益的怪),显然我们需要先从代价小的打起,因为这样可以把生命值越积越多,打代价大的怪也更容易成功。

      那么对于后一部分怎么办呢?我们需要从受益大的打起,为什么?

      证明:

        假设一个怪的受益为back,代价为cost,那么首先假设我们打完所有怪之后剩下have的生命值,那么have的大小是固定的,不会随着操作顺序而改变,因此我们可以考虑用这个来倒推最优策略。

        那么就是要使得这个倒推尽可能成功,观察一下,在倒推的过程中,相当于是不断的后悔打某个怪,那么就相当于减去back,加上cost。

        因此这就是一个和上一部分类似的问题,所以在倒推的时候需要按照back从小到大取,那么从正向来看,就是按照back从大到小取。

     

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define R register int
     4 #define AC 250100
     5 #define LL long long
     6  
     7 int n;
     8 LL have;
     9 int q[AC], top;
    10 struct node{
    11     int cost, back, id;
    12 }s[AC];
    13  
    14 inline int read()
    15 {
    16     int x = 0;char c = getchar();
    17     while(c > '9' || c < '0') c = getchar();
    18     while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    19     return x;
    20 }
    21  
    22 inline bool cmp1(node a, node b){
    23     return a.cost < b.cost;
    24 }
    25  
    26 inline bool cmp2(node a, node b){
    27     return a.back > b.back;
    28 }
    29  
    30 void pre()
    31 {
    32     n = read(), have = read();
    33     for(R i = 1; i <= n; i ++) 
    34         s[i].cost = read(), s[i].back = read(), s[i].id = i;
    35 }
    36  
    37 void work()
    38 {
    39     sort(s + 1, s + n + 1, cmp1);
    40     for(R i = 1; i <= n; i ++)
    41         if(s[i].cost <= s[i].back) 
    42         {
    43             if(s[i].cost >= have) {printf("NIE
    "); return ;}
    44             have += s[i].back - s[i].cost;
    45             q[++top] = s[i].id;
    46         }
    47     sort(s + 1, s + n + 1, cmp2);
    48     for(R i = 1; i <= n; i ++)
    49         if(s[i].cost > s[i].back) 
    50         {
    51             if(s[i].cost >= have) {printf("NIE
    "); return ;}
    52             have += s[i].back - s[i].cost;
    53             q[++top] = s[i].id;
    54         }
    55     printf("TAK
    ");
    56     for(R i = 1; i <= top; i ++) printf("%d ", q[i]);
    57 }
    58  
    59 int main()
    60 {
    61     //freopen("in.in", "r", stdin);
    62     pre();
    63     work();
    64     //fclose(stdin);
    65     return 0;
    66 }
    View Code
  • 相关阅读:
    当公有云Azure拥抱Docker容器技术
    .NET AJAX实例
    漫谈Ajax在.Net中的使用
    .NET运用AJAX 总结及其实例
    Excel自动从身份证中提取生日、性别、年龄
    ASP.NET 与 Ajax 的实现方式
    windows下编辑器Emacs的安装与配置
    2013.10.26工作Fighting(1)
    Jquery操作下拉框(DropDownList)实现取值赋值
    js调用后台,后台调用前台等方法总结
  • 原文地址:https://www.cnblogs.com/ww3113306/p/9867037.html
Copyright © 2020-2023  润新知