zoukankan      html  css  js  c++  java
  • zoj 3410 Layton's Escape

    Layton's Escape

    Time Limit: 2 Seconds      Memory Limit: 65536 KB

    Professor Layton is a renowned archaeologist from London's Gressenheller University. He and his apprentice Luke has solved various mysteries in different places.

    layton.jpg

    Unfortunately, Layton and Luke are trapped in a pyramid now. To escape from this dangerous place, they need to pass N traps. For each trap, they can use Ti minutes to remove it. If they pass an unremoved trap, they will lose 1 HP. They have K HP at the beginning of the escape and they will die at 0 HP.

    Of course, they don't want trigger any traps, but there is a monster chasing them. If they haven't pass the ith trap in Di minutes, the monster will catch and eat them. The time they start to escape is 0, and the time cost on running will be ignored. Please help Layton to escape from the pyramid with the minimal HP cost.

    Input

    There are multiple test cases (no more than 20).

    For each test case, the first line contains two integers N and K (1 <= N <= 25000, 1 <= K <= 5000), then followed by N lines, the ith line contains two integers Ti and Di (0 <= Ti <= 10^9, 0 <= Di <= 10^9).

    Output

    For each test case, if they can escape from the pyramid, output the minimal HP cost, otherwise output -1.

    Sample Input

    3 2
    40 60
    60 90
    80 120
    2 1
    30 120
    60 40
    

    Sample Output

    1
    -1

    总结一下,这道题目比赛的时候本来想到做法了,但是……还是没有想太清楚,总觉得有点儿不对,以为很困难的样子,然后就没有往下想,后来才知道,就是那么做的,贪心的做法。
    首先,要注意,所有陷阱不一定要一次通过,也就是不是那种一关一关地通的那种,也就是说可以随意选择先走哪个,再走哪个。
    做法就是先把每一关怪物到来的时间从小到大排序,又用到了结构体的一级排序。要记住:
    1 struct seg{
    2   int a, b;
    3   friend bool operator < (seg x, seg y){
    4     return x.a < y.a;
    5   }
    6 }x[25000+10];
    7 int cmp(const void *x, const void *y){
    8   return (*(seg*)x).b - (*(seg*)y).b;
    9 }
    
    

    这个就是按照结构体中的变量 b 从小到大排序。然后呢,就是建一个优先队列,为什么用优先队列捏?原因很简单,因为想法就是当遇到一个不能通过的关卡是,我要损失一滴血,跳过其中的一关,那到底跳过哪一关捏?当然是跳过花费自己的时间最长的那一关啊,所以优先队列的作用就是把通过每一关需要花费的时间从大到小排序,这样跳过每一关的时候,只需要pop一个元素就可以了,实际上,当初自己就是这个地方没有想透彻,以为跳过其中一关后可能影响已经通过的其他的关卡的通过与否,事实上,这是不影响的,只要跳过已经通过的当中花费时间最长的那一关,就一定可以通过除了这一关之外的已经通过的所有关卡,包括正在通过的这一关。这样就OK了,另外,还有一个细节,就是当血的数量为0的时候,失败,输出-1,所以,当决定跳过一关的时候,要判断血的数量是不是大于1,而不是大于0!这个边界条件要搞清楚。

    结构体中的friend友元函数,目的是构造优先队列的时候,按照变量 a 的值从大到小排序,方便以后出队。

    学习了一下优先队列,这题WA了一次……

    原来是水题啊,唉。

     1 #include <iostream>
     2 #include <queue>
     3 #include <cstdio>
     4 #include <cstdlib>
     5 #include <cstring>
     6 #include <algorithm>
     7 using namespace std;
     8 struct seg{
     9   int a, b;
    10   friend bool operator < (seg x, seg y){
    11     return x.a < y.a;
    12   }
    13 }x[25000+10];
    14 int cmp(const void *x, const void *y){
    15   return (*(seg*)x).b - (*(seg*)y).b;
    16 }
    17 int main(void){
    18   int n, k;
    19 #ifndef ONLINE_JUDGE
    20   freopen("zoj3410.in", "r", stdin);
    21 #endif
    22   while (~scanf("%d%d", &n, &k)){
    23     int sum = 0, temp = k; bool flag = true;
    24     priority_queue<seg> p;
    25     for (int i = 0; i < n; ++i){
    26       scanf("%d%d", &x[i].a, &x[i].b);
    27     }
    28     qsort(x, n, sizeof(x[0]), cmp);
    29     for (int i = 0; i < n; ++i){
    30       if (!flag) break;
    31       sum += x[i].a; p.push(x[i]);
    32       if (sum <= x[i].b){
    33       }
    34       else {
    35         if (p.size() != 0 && k > 1){
    36           sum -= p.top().a; p.pop(); k--;
    37         }
    38         else{
    39           flag = false;
    40         }
    41       }
    42     }
    43     if (flag) printf("%d\n", temp - k);
    44     else printf("-1\n");
    45   }
    46   return 0;
    47 }

    没看别人的解题报告……自己做的,有成就感,O(∩_∩)O哈哈~

    学习优先队列的测试程序:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstdlib>
     4 #include <queue>
     5 #include <algorithm>
     6 using namespace std;
     7 struct seg{
     8   int a, b;
     9   friend bool operator < (seg x, seg y){
    10     return x.a > y.a;
    11   }
    12 }ti[30];
    13 int main(void){
    14   freopen("priority.in", "r", stdin);
    15   priority_queue<seg> q;
    16   queue<seg> p;
    17   for (int i = 0; i < 3; ++i)
    18   {
    19     scanf("%d%d", &ti[i].a, &ti[i].b);
    20     q.push(ti[i]); p.push(ti[i]);
    21   }
    22   for (int i = 0; i < 3; ++i) 
    23   {printf("%d %d ", q.top().a, q.top().b); q.pop();printf("\n");}
    24   printf("\n");
    25   for (int i = 0; i < 3;++i) 
    26   {printf("%d %d ", p.front().a, p.front().b); p.pop(); printf("\n");}
    27   printf("\n");
    28   return 0;
    29 }

    priority.in文件:

    1 40 60
    2 80 90
    3 60 120

    输出:

    1 40 60
    2 60 120
    3 80 90
    4 
    5 40 60
    6 80 90
    7 60 120
    8 
    9 Hit any key to close this window...

    ^_^

  • 相关阅读:
    拼接表达式树的原理
    ql Server 2012完全卸载方法
    jquery tmpl 详解
    Entity Framework(EF) Code First将实体中的string属性映射成text类型的几种方式
    Entity Framework 数据生成选项DatabaseGenerated
    Entity Framework 复杂类型
    EF Code First 学习笔记:约定配置
    比特币转账流程
    mmap 的理解
    copy_to_user,copy_from_user,get_user,put_user函数比较
  • 原文地址:https://www.cnblogs.com/liuxueyang/p/2972818.html
Copyright © 2011-2022 走看看