2018ICPC焦作站 B - Ultraman vs. Aodzilla and Bodzilla(贪心)

题意:怪兽A攻击力为a1,血量为h1,怪兽B攻击力为a2,血量为h2,奥特曼的第 i 秒的攻击力为 i,问在打死两个怪兽之前奥特曼受到的最小伤害,在伤害值最小的前提下求字典序最小的攻击顺序。

思路:受到的伤害值最小肯定不能俩怪兽一会儿打一下,那必然是打完一个再去打另一个,所以考虑先打死A还是先打死B。

首先求出打死AB的最短时间all,打死A的最短时间a,打死B的最短时间b

1、先打死A

(1)这时花费了a的时间打死了A,若剩余all - a秒可以打死B,就是[1, a]打A,[a + 1, all]打B

(2)如果剩余all - a秒不够打死B,说明第a秒浪费了攻击力,求出浪费值x,可以在第x秒去打B,这样第a秒可以刚好打死A,不会有浪费。所以是[1, x - 1]打A,x打B,[x + 1, a]打A,[a + 1, all]打B

2、先打死B

需要花费b的时间打死B,求出在第b秒浪费的攻击力y,用这y点攻击力尽可能多地在打B之前打A,假设把第1~k秒都改为打A(1 + ... + k <= y)

(1)如果前k秒和第b + 1秒到第all秒足够打死A,就是[1, k]打A,[k +1, b]打死B,[b + 1, all]打死A

(2)如果前k秒和第b + 1秒到第all秒不够打死A,说明在第b秒依旧有浪费,假设还z 的攻击,把前k秒的A往后移,给A造成更大的攻击,为保证字典序最大,只移动第k秒的A,让第k秒打B,第k + z秒打A。所以是[1, k - 1]打A,[k, k + z - 1]打B,k + z打A,[k + z + 1, b]打死B,[b + 1, all]打死A。

这里可以发现一个问题,为什么在1(2)中是求浪费值,而2(2)中是求差值,打死前一个怪兽的浪费值是 >= 打死后一个怪兽的差值的,由于1是先打A,为保证字典序最小,让位置尽可能靠后的换成B,也就是把浪费值用来打B;而2中为保证字典序最小,尽量让A靠前,也就是更换为打A的攻击力尽可能小,所以是差值

好好好好好题

一篇好懂的题解:https://www.cnblogs.com/TheRoadToTheGold/p/14032874.html(最后一种情况不太对,我在这儿改了一下)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int N = 1e5 + 7;
ll p[N];

int main() {
    for(int i = 1; i < N; ++i) p[i] = p[i - 1] + i;
    int t;
    ll a1, a2, h1, h2;
    scanf("%d", &t);
    while(t--) {
        scanf("%lld%lld%lld%lld", &h1, &h2, &a1, &a2);
        string s1 = "", s2 = "";
        ll ans1 = 0, ans2 = 0;
        ll all = lower_bound(p + 1, p + N, h1 + h2) - p;///总
        ll a = lower_bound(p + 1, p + N, h1) - p;       ///A
        ll b = lower_bound(p + 1, p + N, h2) - p;       ///B
        ///A
        ll now = p[all] - p[a];
        ans1 = a * a1 + all * a2;
        if(now >= h2) {
            string tmp1(a, 'A'), tmp2(all - a, 'B');
            s1 = tmp1 + tmp2;
        }
        else {
            ll lost = p[a] - h1;
            string tmp1(lost - 1, 'A'), tmp2(a - lost, 'A'), tmp3(all - a, 'B');
            s1 = tmp1 + "B" + tmp2 + tmp3;
        }
        ///B
        now = p[all] - p[b];
        ll lost = p[b] - h2, it;
        ans2 = b * a2 + all * a1;
        it = upper_bound(p + 1, p + N, lost) - p - 1;
        ll sum = p[it] + now;
        if(sum >= h1) {
            string tmp1(it, 'A'), tmp2(b - it, 'B'), tmp3(all - b, 'A');
            s2 = tmp1 + tmp2 + tmp3;
        }
        else {
            ll left = h1 - now;
            for(int i = 1; i <= b; ++i) {
                if(left >= 2 * i + 1 || left == i) {
                    left -= i;
                    s2 += "A";
                }
                else s2 += "B";
            }
            string tmp(all - b, 'A');
            s2 += tmp;
        }
        if(ans1 < ans2) cout<<ans1<<' '<<s1<<'\n';
        else if(ans1 > ans2) cout<<ans2<<' '<<s2<<'\n';
        else {
            if(s1 < s2) cout<<ans1<<' '<<s1<<'\n';
            else cout<<ans2<<' '<<s2<<'\n';
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43871207/article/details/114231564