• 「AHOI2014/JSOI2014」骑士游戏


    「AHOI2014/JSOI2014」骑士游戏

    传送门
    考虑 ( ext{DP})
    (dp_i) 表示灭种(雾)一只编号为 (i) 的怪物的代价。
    那么转移显然是:

    [dp_i = min(K_i, S_i + sum_{j = 1}^{R_i} dp_{v_j}) ]

    但是我们会发现这个东西是有后效性的。。。
    所以我们会想要用建图然后跑一个最短路什么的来搞。。。
    于是我们观察到上面那个 ( ext{DP}) 式子中,(dp_i) 如果用后面那一项来转移,显然会有 (dp_{v_j} < dp_i)
    这提示我们,为了消除后效性,可以对 (dp) 值排序。
    准确的说就是开一个堆来搞,每个点初始的 (dp) 值都是消灭它的魔法消耗,然后优先更新较小的 (dp) 值,
    毕竟我们对于魔法消耗最小的怪物肯定是直接消灭(因为你到头来都要干死它何必生出一些魔法消耗更高的嘞)
    然后我们建图方式就是反着来,如果 (i) 会生出 (j),那么连边 (j o i),然后我们就跑一个长的有点像 ( ext{Dijkstra})( ext{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
    ", dp[1]);
        return 0;
    }
    
  • 相关阅读:
    在可变字符串类型varchar建立索引时有什么要注意的吗?
    单表行数多少时适合分库分表?
    存储字符串时怎么设计或者考量那?
    小数类型选择float、double正确吗?
    解决mysql java.sql.SQLException: The server time zone value‘XXXXXX' is unrecognized or represents...
    阿里云 Windows Server 2012 密码过期设置
    规则引擎 drools
    day-06
    微信小程序前端开发踩坑(一)
    CornerStone使用跳坑总结(陆续更新)
  • 原文地址:https://www.cnblogs.com/zsbzsb/p/12254210.html
Copyright © 2020-2023  润新知