码迷,mamicode.com
首页 > Web开发 > 详细

「AHOI2014/JSOI2014」骑士游戏

时间:2020-02-02 23:18:50      阅读:95      评论:0      收藏:0      [点我收藏+]

标签:code   operator   continue   初始   mes   etc   oid   define   tps   

「AHOI2014/JSOI2014」骑士游戏

传送门
考虑 \(\text{DP}\)
\(dp_i\) 表示灭种(雾)一只编号为 \(i\) 的怪物的代价。
那么转移显然是:
\[dp_i = \min(K_i, S_i + \sum_{j = 1}^{R_i} dp_{v_j})\]
但是我们会发现这个东西是有后效性的。。。
所以我们会想要用建图然后跑一个最短路什么的来搞。。。
于是我们观察到上面那个 \(\text{DP}\) 式子中,\(dp_i\) 如果用后面那一项来转移,显然会有 \(dp_{v_j} < dp_i\)
这提示我们,为了消除后效性,可以对 \(dp\) 值排序。
准确的说就是开一个堆来搞,每个点初始的 \(dp\) 值都是消灭它的魔法消耗,然后优先更新较小的 \(dp\) 值,
毕竟我们对于魔法消耗最小的怪物肯定是直接消灭(因为你到头来都要干死它何必生出一些魔法消耗更高的嘞)
然后我们建图方式就是反着来,如果 \(i\) 会生出 \(j\),那么连边 \(j \to i\),然后我们就跑一个长的有点像 \(\text{Dijkstra}\)\(\text{DP}\) 就好了。
参考代码:

#include <cstdio>
#include <queue>
#define rg register
#define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
using namespace std;
template < class T > inline void read(T& s) {
    s = 0; int f = 0; char c = getchar();
    while ('0' > c || c > '9') f |= c == '-', c = getchar();
    while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar();
    s = f ? -s : s;
}

typedef long long LL;
const int _ = 2e5 + 5, __ = 1e6 + 5;

int tot, head[_]; struct Edge { int ver, nxt; } edge[__];
inline void Add_edge(int u, int v) { edge[++tot] = (Edge) { v, head[u] }, head[u] = tot; }

int n, r[_], vis[_]; LL dp[_], s[_], k[_];
struct node { int u; LL val; } ;
inline bool operator < (const node& x, const node& y) { return x.val > y.val; }

priority_queue < node > Q;

int main() {
#ifndef ONLINE_JUDGE
    file("cpp");
#endif
    read(n);
    for (rg int i = 1; i <= n; ++i) {
        read(s[i]), read(k[i]), read(r[i]);
        for (rg int x, o = 1; o <= r[i]; ++o) read(x), Add_edge(x, i);
    }
    for (rg int i = 1; i <= n; ++i) Q.push((node) { i, dp[i] = k[i] });
    while (!Q.empty()) {
        int u = Q.top().u; Q.pop();
        if (vis[u]) continue ; vis[u] = 1;
        for (rg int i = head[u]; i; i = edge[i].nxt) {
            int v = edge[i].ver;
            s[v] += dp[u];
            if (dp[v] > s[v] && !--r[v])
                dp[v] = s[v], Q.push((node) { v, dp[v] });
        }
    }
    printf("%lld\n", dp[1]);
    return 0;
}

「AHOI2014/JSOI2014」骑士游戏

标签:code   operator   continue   初始   mes   etc   oid   define   tps   

原文地址:https://www.cnblogs.com/zsbzsb/p/12254210.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!