2018NingXia-H. Fight Against Monsters

版权声明:转载请注明 https://blog.csdn.net/li13168690086/article/details/81096951

  题目描述

   计蒜客链接

  It is my great honour to introduce myself to you here. My name is Aloysius Benjy Cobweb Dartagnan Egbert Felix Gaspar Humbert Ignatius Jayden Kasper Leroy Maximilian. As a storyteller, today I decide to tell you and others a story about the hero Huriyyah, and the monsters.

  Once upon a time, citizens in the city were suffering from n powerful monsters. They ate small children who went out alone and even killed innocent persons. Before the hero appeared, the apprehension(不安) had overwhelmed the people for several decades. For the good of these unfortunate citizens, Huriyyah set o to the forest which was the main lair of monsters and fought with n fierce and cruel monsters. The health point of the i-th monster was HPi, and its attack value was ATKi.

  They fought in a cave through a turn-based battle. During each second, the hero Huriyyah was attacked by monsters at first, and the damage was the sum of attack values of all alive monsters. Then he selected a monster and attacked it. The monster would suffer the damage of k (its health point would decrease by k) which was the times of attacks it had been came under. That is to say, for each monster, the damage of the first time that Huriyyah attacked it was 1, and the damage of Huriyyah’s second attack to this monster was 2, the third time to this monster was 3, and so on. If at some time, the health point of a monster was less than or equal to zero, it died. The hero won if all monsters were killed.

  Now, my smart audience, can you calculate the minimum amount of total damages our hero should su er before he won the battle?

输入格式

第一行包含一个整数 T,表示有 T 组测试数据。
接下来依次描述 T 组测试数据。对于每组测试数据:
第一行包含一个整数 n,表示怪兽的数量。
接下来 n 行,每行包含两个整数 HPi, AT Ki,表示每只怪兽的体力值和攻击值。

输出格式

对于每组测试数据,输出一行信息 "Case #x: y"(不含引号),其中 x 表示这是第 x 组测试数据, y 表示战斗过程中受到的伤害之和的最小值。

样例输入

2

3

1 1

2 2

3 3

3

3 1

2 2

1 3

样例输出

Case #1: 19

Case #2: 14

题目理解

1.读题(注意划横线句子)

 跳过第一段。

 着眼第二段最后两句话:可以知道这是一个打怪兽的情景,每个怪兽有血量和攻击值。

 接下来第三段很重要,告诉我们男主如何打怪兽。他要与怪兽们交战多个回合,可自主选择和哪个怪兽战斗。每次交战只能打一只怪,并且在每回合出手前,男主要受到剩余怪兽们(包括当前这只)的全部攻击。交战时,男主对怪进行多次攻击,攻击力单调递增,初始值为1,公差为1(即第一次攻击为1,第二次为2,第三次为3),当怪兽的血量被攻击后小于或等于0,死亡。

 第四段告诉我们,需要计算出男主在杀死所有怪兽的情况下,受到总伤害的最小值。

解题思路

  题目大意是要我们安排男主的攻击顺序,即怪兽被打的顺序。顺着继续思考:怎样挑选怪兽,可以使得男主受到的伤害最小。这很符合贪心的特点,所以应该属于贪心问题,那么最重要的是排序规则。

  我们一开始可能会想以怪兽的血量大小来排序,但忽略怪兽的攻击值;或者想以怪兽的攻击值来排序,却又忽略的怪兽的血量。所以权衡之下,应该把怪兽的血量和攻击值同时一起考虑。那么就有两种思路:

(思路1) 花尽可能少的次数击杀伤害值高的怪兽。

(思路2) 在攻击一只怪兽时,要受到其他怪物的伤害最小。

 思路1所代表的意义则是,挑选击倒某只怪兽的次数很少,且这只怪兽的攻击力很高,转换为代码则是: time/atk 的比值越小的越好。

 思路2关注点在怪兽的攻击,男主面对小怪A和小怪B时,受到另一只怪的伤害为B.atk * A.time(B怪的攻击乘击倒A怪的次数) 或者A.atk * B.time(同理)。转为代码为比较B.atk * A.time和A.atk * B.time谁小就选谁。

有了这两个思路,我们需要求出击倒每只怪物的次数(1.先用数组算好男主递增的攻击力,然后每次用二分搜索匹配;2.或者每次模拟被打倒的过程,得出次数。),然后写出排序规则(return B.atk * A.time<A.atk * B.time 或者return A.atk * B.time > B.atk * A.time)如果选择思路1,也将除法转换为乘法,因为除法涉及精度问题,所以为了省事用整数乘法即可;最后注意测试值的大小和范围,整型用LONG LONG,以及输出格式

AC代码

#include <iostream>
#include <algorithm>
#include <math.h>
using namespace std;
const int MAXN=1e5+5;
struct monster{
    int h;
    int atk;
    long long time;
}k[MAXN];

bool cmp(monster a,monster b)
{
    return  b.atk*a.time < a.atk*b.time;  //由a.time/a.p < b.time/b.p变形而来
}

int main(){
    int t;
    cin >> t;
    for(int j = 1; j <= t; j++){
        int n;
        long long hart = 0;     //长整型适合测试值大小
        long long ans = 0;
        scanf("%d",&n);
        for(int i = 0; i < n; i++){
            scanf("%d %d",&k[i].h,&k[i].atk);
            hart += k[i].atk;
            int r = 1, time = 0;
            while(k[i].h > 0){   //模拟击倒过程
                k[i].h -= r;
                r++;
                time++;
            }
            k[i].time = time;
        }
        sort(k,k+n,cmp);
        for(int i = 0; i < n; i++){
            ans += hart*k[i].time;
            hart -= k[i].atk;
        }
        printf("Case #%d: %lld\n",j,ans);  //注意输出格式
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/li13168690086/article/details/81096951