2018ICPC Jiaozuo Station B-Ultraman vs. Aodzilla and Bodzilla (greedy)

Question: Monster A’s attack power is a1, its HP is h1, monster B’s attack power is a2, its HP is h2, and Ultraman’s attack power in the i second is i. Ask before killing two monsters. For the minimum damage that Man receives, find the attack order with the least lexicographical order on the premise of the smallest damage value.

Idea: The minimum damage value must not be a fight between two monsters for a while. It must be to fight one after the other, so consider whether to kill A or B first.

First find the shortest time all to kill AB, the shortest time a to kill A, and the shortest time b to kill B

1. Kill A first

(1) At this time, it took a’s time to kill A. If all-a seconds are left to kill B, then [1, a] beats A, [a + 1, all] beats B

(2) If the remaining all-a seconds are not enough to kill B, it means that the attack power was wasted in the a second. If you find the wasted value x , you can hit B in the x second, so that you can just kill A in the a second. There is waste. So [1, x-1] hits A, x hits B, [x + 1, a] hits A, [a + 1, all] hits B

2. Kill B first

It takes b’s time to kill B, find the wasted attack power y in the b-th second, and use this y-point attack power to hit A before hitting B as much as possible, assuming that the first to k seconds are changed to hit A (1 + ... + k <= y)

(1) If the first k seconds and the b + 1 second to the all second are enough to kill A, then [1, k] will kill A, [k +1, b] will kill B, [b + 1, all] Die A

(2) if the second and the first k b + 1 to second all A second not killed, b described in the first seconds still have wasted, further assumed lack z attack, before the second A k moved back, to the A To cause a bigger attack, in order to ensure the largest lexicographical order, only move A in the kth second, let the kth second hit B, and the k+z second hit A. So [1, k-1] beats A, [k, k + z-1] beats B, k + z beats A, [k + z + 1, b] beats B, [b + 1, all] Kill A.

 

One problem can be found here, why is the waste value in 1 (2) and the difference in 2 (2). The waste value of the monster before killing is >= the difference of the monster after killing. Since 1 is to hit A first, in order to ensure that the lexicographical order is the smallest, the position as far back as possible is replaced with B, that is, the waste value is used to hit B; and in 2, to ensure the smallest lexicographical order, try to make A as high as possible. The attack power of changing to A is as small as possible, so it’s a difference

Good question

An easy-to-understand solution: https://www.cnblogs.com/TheRoadToTheGold/p/14032874.html (The last situation is not quite right, I changed it here)

#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;
}

 

Guess you like

Origin blog.csdn.net/weixin_43871207/article/details/114231564