poj2152(Fire) 樹形DP

來源:互聯網
上載者:User

標籤:style   class   blog   code   http   com   

題目連結:http://poj.org/problem?id=2152

題意:一棵帶邊權的樹,邊權表示節點間距離,在i上建立消防站的代價是w[i],如果在一點i沒建消防站,那麼它與距離這個點最近的消防站之間的距離不能大於d[i]。問滿足建站最小的花費;


解法;看了陳啟峰的論文才會的,感覺挺難的,不過論文裡分情況討論了,應該不需要;dp[i][j]表示在i處選擇j處作為供應站(但是並不一定要求是最近的,這樣即使有更近的也無所謂,和論文裡有出入。),best[i]表示i及其子樹滿足要求的最小花費,那麼轉移方程:

     best[i]=min(dp[i][j]),1<=j<=n

     dp[i][j]=w[j]+min(dp[k][j]-w[j],best[k]),k是i的兒子


代碼:

/******************************************************* @author:xiefubao*******************************************************/#pragma comment(linker, "/STACK:102400000,102400000")#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>#include <queue>#include <vector>#include <algorithm>#include <cmath>#include <map>#include <set>#include <stack>#include <string.h>//freopen ("in.txt" , "r" , stdin);using namespace std;#define eps 1e-8#define zero(_) (abs(_)<=eps)const double pi=acos(-1.0);typedef long long LL;const int Max=100010;const int INF=1e9+7;int n;int cost[1010];int d[1010];int dist[1010];int dp[1010][1010];int best[1010];vector<pair<int,int> > vec[1010];void add(int a,int b,int c){    vec[a].push_back(pair<int,int>(b,c));    vec[b].push_back(pair<int,int>(a,c));}void getdist(int u,int before,int add){    dist[u]=dist[before]+add;    for(int i=0; i<vec[u].size(); i++)        if(vec[u][i].first!=before)        getdist(vec[u][i].first,u,vec[u][i].second);}void dfs(int u,int before){    //cout<<u<<" "<<before<<endl;    for(int i=0; i<vec[u].size(); i++)    {        if(vec[u][i].first==before)            continue;        dfs(vec[u][i].first,u);    }    dist[u]=0;    getdist(u,0,0);    for(int i=1; i<=n; i++)        if(dist[i]<=d[u])        {            dp[u][i]=cost[i];            for(int k=0; k<vec[u].size(); k++)                if(vec[u][k].first!=before)                dp[u][i]+=min(dp[vec[u][k].first][i]-cost[i],best[vec[u][k].first]);            best[u]=min(best[u],dp[u][i]);        }        else            dp[u][i]=INF;}int main(){    int t;    cin>>t;    while(t--)    {        scanf("%d",&n);        for(int i=0; i<=n; i++)            vec[i].clear();        for(int i=1; i<=n; i++)            scanf("%d",cost+i);        for(int i=1; i<=n; i++)            scanf("%d",d+i);        for(int i=0; i<n-1; i++)        {            int a,b,c;            scanf("%d%d%d",&a,&b,&c);            add(a,b,c);        }        for(int i=1; i<=n; i++)            best[i]=INF;        dfs(1,0);        cout<<best[1]<<endl;    }    return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.