poj 2152 一道很难的树型DP

原创 2012年07月26日 11:17:44

题目:poj 2152  Fire

         我想说的:以前做背包的题目做多了,脑子形成了一种就是所有动态规划就是在数组上进行等一些固定的思想。结果最近在做一些题目的时候,感觉无从下手,想好久都没结果。非常庆幸自己做了这类题目,让我从那种狭隘的思想中做出来。以后就要根据实际情况研究状态了。

         题意:有n个城市,每两个城市只有一条路连接,(所以可以当成是一颗树)。现在要建设一些防火站,使每个城市都可以被覆盖。每个城市的属性是:在本城市建防火站的价钱和不在本城市建设的话,所依赖的别的防火站的最长距离。然后是n-1条路,和这条路的长度。现在问在覆盖所有城市的前提下的最少价格。

         解题:首先要说的是,感觉这个题目很难,自己想了一天,然后看了一天的解题报告,包括国家集训队论文,陈启峰2006年的一张一弛,解题之道 ——“约制、放宽”方法在解题中的应用》,结果还是不明白,最后只有对着讲解,看代码,模拟,最后又花费了一上午的时间理解了一个大概,现在就用自己理解的来说一下吧。

        dp[i][j]:表示以i为根的子树里修建一些消防站,并在节点j处修建一消防站,i的负责站必须是j;

    best[i]:表示表示以i为根的子树的所有节点都有负责站的最小花费。

    dist[i]:表示i到x的距离(每换换一个节点,都要再求一次dist[])。

    状态状态转移方程:dp[i][j]=w[j]+sum(min(best[y],dp[y][j]-w[i]))(y是i的所有孩子);

哎!不是很理解,所有也就能写这么多了,在网上搜了一个详细的,大家可以参考这个poj 2152 Fire

个人代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
#define N 1010
#define M (1<<30)
struct City{
    int d,w;
}city[N];
struct lianjie{
    int child,d;
    lianjie(int x,int y)
    {
        child=x;d=y;
    }
};
vector <lianjie> tree[N];
int num,dist[N],best[N],dp[N][N];
void init()
{
    scanf("%d",&num);
    int i,u,v,l;
    for(i=1;i<=num;i++) tree[i].clear();
    for(i=1;i<=num;i++) scanf("%d",&city[i].w);
    for(i=1;i<=num;i++) scanf("%d",&city[i].d);
    for(i=1;i<num;i++)
    {
        scanf("%d%d%d",&u,&v,&l);
        tree[u].push_back(lianjie(v,l));
        tree[v].push_back(lianjie(u,l));
    }
}
void dis(int key)
{
    int length=tree[key].size();
    for(int i=0;i<length;i++)
    {
        int v=tree[key][i].child;
        if(dist[v]!=-1) continue;
        dist[v]=dist[key]+tree[key][i].d;
        dis(v);
    }
}
void dfs(int key,int parent)
{
    int i,j,v,length=tree[key].size();

    for(i=0;i<length;i++)
    {
        v=tree[key][i].child;
        if(v!=parent)        dfs(v,key);
    }
    memset(dist,-1,sizeof(dist));
    dist[key]=0;    best[key]=M;    dis(key);
    for(i=1;i<=num;i++)
    {
        if(dist[i]>city[key].d) dp[key][i]=M;
        else
        {
            dp[key][i]=city[i].w;
            for(j=0;j<length;j++)
            {
                v=tree[key][j].child;
                if(v!=parent)
                dp[key][i]+=min(best[v],dp[v][i]-city[i].w);
            }
            best[key]=min(best[key],dp[key][i]);
        }
    }
}
int main()
{
    //freopen("/home/acm/JPY/input.txt","r",stdin);
    int T;cin>>T;
    while(T--)
    {
        init();        dfs(1,0);
        cout<<best[1]<<endl;
    }
    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

poj2152(Fire) 树形DP

题目链接:http://poj.org/problem?id=2152 题意:一棵带边权的树,边权表示节点间距离,在i上建立消防站的代价是w[i],如果在一点i没建消防站,那么它与距离这个点最近的消...

鸣人和佐助

描述 佐助被大蛇丸诱骗走了,鸣人在多少时间内能追上他呢? 已知一张地图(以二维矩阵的形式表示)以及佐助和鸣人的位置。地图上的每个位置都可以走到,只不过有些位置上有大蛇丸的手下,需要先打败大...

POJ2152 树形DP

题意:这一题是陈启锋的论文中

【poj2152】【Fire】【树形dp】

Fire Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 1161 Accepted: 595 Descr...

Currency Exchange (POJ 1860)

Description Several currency exchange points are working in our city. Let us suppose that each poin...

POJ 2152 树型DP //很棒的题

题意:Z国有n个城市,从1到n给这些城市编号。城市之间连着高速公路,并且每两个城市之间有且只有一条通路。不同的高速公路可能有不同的长度。最近Z国经常发生火灾,所以当地政府决定在某些城市修建一些消防站。...

POJ 2152 Fire(依赖型树形dp)

题目链接: POJ 2152 Fire 题意: 给一个nn个节点和n−1n-1条边的树,边权代表距离,要在这些点中选择一些点建立消防站,使得每个点都会被消防站覆盖到。每个点有两个属性:cost...

POJ 1655 Balancing Act 树型DP 树的重心 板题

我相信紫书上说的已经很清楚了,DFS一遍就好         首先随便找一个点为根节点,状态的定义是dp[i]表示i的子树的节点个数(包括他自己),所以实际上该点的最大子树数目就是max(dp[j],...

poj 1155 TELE(树型DP)

没有注意时间,已经写了三个小时了。         好久时间没有做过背包问题,就找了一道练练手。再加上xcode用的还不是很熟练,硬是写了三个小时。         题目的时限和空间放的很宽,我写...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)