POJ - 2152 Fire 【树形dp + 暴力 + 思维】

传送门
//题意: 现在有些城市着火了, 需要建立一定数量的消防站, 每一个点建站有一个不同的花费, 有边权, 如果一个城市没有建立消防站 , 那么至少离他一个limit的距离比较有个消防站, 不同的点limit也不同, 问满足条件的最小花费是多少?
//思路: 我们并不能通过一次遍历而得到我们需要的答案. 我们可以考虑暴力判断每一个点是否可以作为当前点的依附点(即在这个点建立消防站), 那么我们就有一个n^2的算法, 综合数据发现, 这个n最大也只是1000, 所以n^2是完全够的, 为了实现这个求解我们需要一些辅助数组.
best[x] 代表的是x的子树下满足题意的最小花费是多少. 显然最后答案就是best[1].
dp[u]][j] 代表的是u依附于j时u的子树内满足条件的最小花费是多少. (j就是我们暴力判断的每一个点)

转移方程就是:
best[x] = min(dp[x][j],best[x]);
dp[u][j] = sum( min(dp[v][j] - cost[j], best[v]) );

那么就可以写啦

AC Code

const int maxn = 1e3+5;
int cas=1;
int cnt ,head[maxn];
int dis[maxn][maxn];
int cost[maxn],limit[maxn];
int best[maxn],dp[maxn][maxn];
struct node
{
    int to,w,next;
}e[maxn<<1];

void add(int u,int v,int w)
{
    e[cnt] = (node){v,w,head[u]};
    head[u] = cnt++;
}
int root,n;
void dfs_dis(int u,int fa,int len)//预处理出所有点对之间的距离.
{
    dis[root][u] = len;
    for(int i=head[u]; ~i ; i = e[i].next){
        int to = e[i].to;
        if(to == fa) continue;
        dfs_dis(to,u,len+e[i].w);
    }
}

void dfs(int u,int fa)
{
    for(int i=head[u]; ~i ; i=e[i].next){
        int to = e[i].to;
        if(to == fa) continue;
        dfs(to,u);    //递归到叶子结点在进行操作.
    }
    for(int i=1;i<=n;i++){   //暴力枚举每一个点寻找最优解.
        if(dis[i][u]>limit[u]) continue;  //距离不符合
        dp[u][i] = cost[i];
        for(int j=head[u]; ~j ; j = e[j].next){
            int to = e[j].to;
            if(to == fa) continue;
            dp[u][i] += min(dp[to][i] - cost[i],best[to]);
            //如果v,i没有依赖关系,则dp[v][i] = inf;
        }
        best[u] = min(dp[u][i],best[u]);
    }
}

void solve()
{
    while(~scanf("%d",&n)){
        for(int i=1;i<=n;i++) scanf("%d",&cost[i]);
        for(int i=1;i<=n;i++) scanf("%d",&limit[i]);
        cnt = 0; Fill(head,-1);
        for(int i=1;iint u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w); add(v,u,w);
        }
        Fill(dis,inf);
        for(int i=1;i<=n;i++) dfs_dis(root = i,-1,0);
        Fill(dp,inf); Fill(best,inf);
        dfs(1,-1);
        cout << best[1] << endl;
    }
}

你可能感兴趣的:(树形dp)