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

DescriptionCountry Z has N cities, which are numbered from 1 to N. Cities are connected by highways,...
  • LOI_DQS
  • LOI_DQS
  • 2016年03月13日 15:53
  • 470

poj2152(Fire) 树形DP

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

POJ2152 树形DP

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

【SDOI2009】【BZOJ1879】Bill的挑战

Description Input本题包含多组数据。 第一行:一个整数T,表示数据的个数。 对于每组数据: 第一行:两个整数,N和K(含义如题目表述)。 接下来N行:每行一个字符串。 Output...

poj1155 TELE(树形dp+背包)

TELE Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4344   Accepted:...
  • d_x_d
  • d_x_d
  • 2015年11月16日 20:06
  • 1458

POJ 2152 树型DP //很棒的题

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

POJ 2152 Fire(依赖型树形dp)

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

poj 1463 Strategic game 树型dp,最小点集覆盖

题目:http://poj.org/problem?id=1463 题意:给一颗树,用最少的点把所有的边覆盖了。可以用动态规划,也可以用最小点集覆盖(最裸的题目)。 很水的一个题目,又是一个树的遍...

POJ 3162 Walking Race(单调队列或线段树加树型DP)

题意:给你一棵有n个节点的树,树边为权值,要你求出树上每个点到其他点的距离中最大的那个值。对求出的从节点1到节点n最大值,找出最长的一段使得这一段中最大值减最小值的结点小于等于m。 对于第一个问题,...

poj3345 树型DP

这题不难,输入较繁,典型的树形dp 题目大意:一共有n( 在树上背包,代码: for (k=0;k     {         y=g[x][k];         for (i=nu...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:poj 2152 一道很难的树型DP
举报原因:
原因补充:

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