码迷,mamicode.com
首页 > 其他好文 > 详细

POJ - 2152 Fire 树型DP

时间:2015-05-16 14:52:57      阅读:184      评论:0      收藏:0      [点我收藏+]

标签:

题目大意:有N座城市,要求在这N座城市中建一个消防系统,使得每座城市城市着火时都能被按时扑灭
现在给出每座城市建一个消防站所需的花费w和每座城市相邻消防站的最远距离lim(和该城市距离超过lim的城市的消防站无法救该城市的火),问要使所有的城市都能被救到火,建消防站的最小花费是多少

解题思路:参考了别人的题解,果然还是太弱了。。。
要使该城市能被救到火,那么消防站不是建在该点,就是建在以该点为根的子树上,或者是该点的父节点上,他肯定要依赖其中一个城市的消防站的
设dp[i][j]表示以i城市为根的树依赖j城市消防站的最低花费(该树的每个节点都符合要求),best[i]为以i城市为根的树最低消费(该树的所有节点都符合要求)
那么状态转移方程就是
dp[i][j] = w[j] + sum (min(dp[k][j] - w[j], best[k])) (k为i的子节点)
dp[k][j]表示因为k可以和i节点一样依赖于j,那么花费就是dp[k][j] - w[j],或者k节点不依赖于j,而依赖于别的节点,那就是best[k]了
以上参考了:http://blog.csdn.net/woshi250hua/article/details/7725917

#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
#define maxn 1010
#define INF 0x3f3f3f3f
struct Node{
    int v, l;
    Node() {}
    Node(int vv, int ll) {
        v = vv;
        l = ll;
    }
};
vector<Node> node[maxn];
int dp[maxn][maxn], dis[maxn][maxn], w[maxn], lim[maxn], best[maxn];
int n, now;

void dfs(int cur, int f, int d) {
    dis[now][cur] = d;
    int u;
    for(int i = 0; i < node[cur].size(); i++) {
        if( ( u = node[cur][i].v) != f) 
            dfs(u,cur,d + node[cur][i].l);
    }
}

void init() {
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        node[i].clear();
        best[i] = INF;
    }

    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
            dp[i][j] = INF;
    for(int i = 1; i <= n; i++)
        scanf("%d", &w[i]);
    for(int i = 1; i <= n; i++)
        scanf("%d", &lim[i]);
    int x, y, z;
    for(int i = 0; i < n - 1; i++) {
        scanf("%d%d%d", &x, &y, &z);
        node[x].push_back(Node(y,z));
        node[y].push_back(Node(x,z));
    }

    for(int i = 1; i <= n; i++) {
        now = i;
        dfs(i,0,0);
    }
}

void DP(int cur, int f) {
    int u;
    for(int i = 0; i < node[cur].size(); i++)
        if((u = node[cur][i].v) != f)
            DP(u, cur);

    for(int i = 1; i <= n; i++) {
        if(dis[cur][i] <= lim[cur])
            dp[cur][i] = w[i];
        for(int j = 0; j < node[cur].size(); j++) {
            if((u = node[cur][j].v) != f) {
                dp[cur][i] += min(dp[u][i] - w[i], best[u]);
            }
        }
        best[cur] = min(dp[cur][i], best[cur]);
    }
}

int main() {
    int test;
    scanf("%d", &test);
    while(test--) {
        init();
        DP(1,0);
        printf("%d\n", best[1]);
    }
    return 0;
}

POJ - 2152 Fire 树型DP

标签:

原文地址:http://blog.csdn.net/l123012013048/article/details/45768047

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