ZRDay6A. Newly demolished tower (ternary pressure dp)

Keywords: C++

meaning of the title

 

Sol

It's like the first time I've been exposed to ternary pressure

First of all, it's not necessarily the best to eat gems after each fight, because there are imitation monsters, maybe you can hit GG after you finish eating gems with him..

So there are three states that we need to maintain

0: no fight

1: I beat the monster and didn't eat the gem

2: Beat the monster and eat the gem

If we can know that we hit those monsters and ate those gems, then the state at this time will be determined and preprocessed

Then DP will do

The card constant of mdzz

/*
It's not necessarily the best way to eat gems after the first fight
So we need to name the state of each monster
0: Not hit 
1: I beat the monster and didn't eat the gem
2: Beat the monster and eat the gem
If we can know that we hit those monsters and ate those gems, then the state at this time will be determined
 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<vector>
#include<set>
#include<queue>
#include<cmath>
//#define int long long 
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1<<22, stdin), p1 == p2) ? EOF : *p1++)
char buf[(1 << 22)], *p1 = buf, *p2 = buf;
#define LL long long 
using namespace std;
const int MAXN = 2 * 1e6 + 10;
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int T, N;
int lim, Hp, A, F, M, Mp[MAXN], IA[MAXN], IF[MAXN], IM[MAXN];//Attack HP defense magic defense 
LL f[MAXN], Po[16];
struct Enemy {
    int H, A, D, S, ap, dp, mp, hp;
}a[15];
vector<int> v[16];
void init() {
    memset(f, 0, sizeof(f));
    Hp = read(); A = read(); F = read(); M = read();
    N = read();    
    lim = Po[N];
    for(int i = 1; i <= N; i++) {
        a[i].H = read();  a[i].A = read(); a[i].D = read(); a[i].S = read(); 
        a[i].ap = read(); a[i].dp = read(); a[i].mp = read(); a[i].hp = read();
    }
    int K = read();
    for(int i = 1; i <= N; i++) v[i].clear();
    for(int i = 1; i <= K; i++) {
        int u = read(), vv = read();
        v[vv].push_back(u);
    }
}
LL Attack(int sta, int id) {
    LL Now = f[sta], A = IA[sta], D = IF[sta], M = IM[sta];
    LL s = a[id].S, h = a[id].H, aa = a[id].A, d = a[id].D;
    if (s & 8) aa = A, d = D; // imitate 
    if (s & 2) D = 0; // Defying defense 
    LL AA = max(0ll, A - d); // Warrior deals damage 
    aa = max(0ll, aa - D) * (((s >> 2) & 1) + 1); // Attack power caused by monsters, whether to attack continuously 
    if (AA == 0) return 0; 
    LL t1 = (h - 1) / AA + 1; // How many times do I need to fight 
    LL t2 = (s & 1) ? (t1 * aa) : ((t1 - 1) * aa); // Attack power caused by monsters, whether there is a preemptive attack 
    LL t3 = max(0ll, t2 - M); // Minus magic defense 
    return max(0ll, Now - t3);
}
void solve() {
    f[0] = Hp;
    for(int sta = 0; sta < lim; sta++) {
        IA[sta] = A; IF[sta] = F; IM[sta] = M;
        for(int i = 1; i <= N; i++) 
            if(sta / Po[i - 1] % 3 == 2)
                IA[sta] += a[i].ap, IF[sta] += a[i].dp, IM[sta] += a[i].mp;         
    }
    for(int sta = 0; sta < lim; sta++) {
        if(f[sta] == 0) continue;
        for(int i = 1; i <= N; i++) {
            if(sta / Po[i - 1] % 3 == 0) {// not kill 
                bool flag = 0;
                for(int j = 0; j < v[i].size(); j++) 
                    if(sta / Po[v[i][j] - 1] % 3 == 0) // not kiil
                        {flag = 1; break;}
                if(flag == 1) continue;
                LL nhp = Attack(sta, i);
                if(nhp > 0) 
                    f[sta + Po[i - 1]] = max(f[sta + Po[i - 1]], nhp);
            } else if(sta / Po[i - 1] % 3 == 1) {
                f[sta + Po[i - 1]] = max(f[sta + Po[i - 1]], f[sta] + a[i].hp);
            }
        }
    }
    printf("%lld\n", f[lim - 1] == 0 ? -1 : f[lim - 1]);
}
main() {
    Po[0] = 1;
    for(int i = 1; i <= 15; i++) Po[i] = 3 * Po[i - 1];
    T = read();
    while(T--) {
        init();
        solve(); 
    }
    return 0;
}
/*
2 2 1
1 1
2 1 1
*/

Posted by pillot1005 on Tue, 31 Dec 2019 02:30:20 -0800