洛谷 P4037 [JSOI2008]魔兽地图

经典树形 dp,很早就想做了,但一直没有时间做(懒)。
做法其实我也早就知道了,但是代码打出来却总是 TLE,调了好久,越调越乱,最后重写一边就过了。???

#include <cstdio>
#include <cstring>

inline int max(const int& a, const int& b){
    return a > b ? a : b;
}

inline int min(const int& a, const int& b){
    return a < b ? a : b;
}

const int MAXN = 5e1 + 9, MAXM = 2e3 + 9, MAXC = 1e2 + 9;

struct Edge{
    int to, next, dist;
}edge[MAXN * MAXN];

int cnt, head[MAXN];

inline void add(int from, int to, int dist){
    edge[++cnt].to = to;
    edge[cnt].dist = dist;
    edge[cnt].next = head[from];
    head[from] = cnt;
}

int power[MAXN], f[MAXN][MAXM][MAXC], dp[MAXM];
int n, m;
bool isleaf[MAXN], nottop[MAXN];
int price[MAXN], limit[MAXN];
int g[MAXN][MAXM];

void dfs(int node){
    if(isleaf[node]){
        for(int i = 0; i <= limit[node] && i * price[node] <= m; ++i)
            for(int j = 0; j <= i; ++j)
                f[node][i * price[node]][j] = power[node] * (i - j);
        return;
    }
    limit[node] = 0x7fffffff;
    for(int i = head[node]; i; i = edge[i].next)
        dfs(edge[i].to), limit[node] = min(limit[node], limit[edge[i].to] / edge[i].dist);
    for(int i = 0; i <= limit[node]; ++i){
        cnt = 0;
        std::memset(g, -0x3f3f3f3f, sizeof g);
        g[0][0] = 0;
        for(int j = head[node]; j; j = edge[j].next){
            ++cnt;
            for(int k = 0; k <= m; ++k)
                for(int l = 0; l <= k; ++l)
                    g[cnt][k] = max(g[cnt][k], g[cnt - 1][k - l] + f[edge[j].to][l][i * edge[j].dist]);
        }
        for(int j = 0; j <= m; ++j)
            for(int k = 0; k <= i; ++k)
                f[node][j][k] = max(f[node][j][k], g[cnt][j] + power[node] * (i - k));
    }
}

int main(int argv, char *argc[]){
    std::scanf("%d%d", &n, &m);
    std::memset(f, -0x3f3f3f3f, sizeof f);
    for(int i = 1; i <= n; ++i){
        std::scanf("%d", power + i);
        std::getchar();
        if(std::getchar() == 'A'){
            int c, type, num;
            std::scanf("%d", &c);
            for(int j = 1; j <= c; ++j){
                std::scanf("%d%d", &type, &num);
                add(i, type, num);
                nottop[type] = true;
            }
        }
        else{
            isleaf[i] = true;
            std::scanf("%d%d", price + i, limit + i);
        }
    }
    for(int i = 1; i <= n; ++i)
        if(!nottop[i]){
            dfs(i);
            for(int j = m; j >= 1; --j)
                for(int k = 1; k <= j; ++k)
                    dp[j] = max(dp[j], dp[j - k] + f[i][k][0]);
        }
    int ans = 0;
    for(int i = 1; i <= m; ++i)
        ans = max(ans, dp[i]);
    std::printf("%d\n", ans);
    return 0;
}

原来我会不定期心情烦躁,代码混乱,想起一个变量就当场定义一个,想起一个函数就当场写一个,结果思路、代码都变成一团乱麻,还不如重写。以后一定要多想,少写。

猜你喜欢

转载自www.cnblogs.com/natsuka/p/12534240.html