zoukankan      html  css  js  c++  java
  • POJ-2152 Fire (树形DP)

    题目大意:在一棵树中选出一些点,选每个点的代价为w(i),并且对于点 i ,在距离它lim(i)之内必须选一个点,使它作为 i 的依赖点。求最小代价。

    题目分析:定义状态dp(u,k)表示使u为根节点的子树满足题意并且节点u依赖节点k产生的最小代价,定义best(u)表示子树u满足题意得最小代价。则状态转移方程为:

    dp(u,k)=w(k)+∑min(dp(v,k)-w(k),best(v))  dist(u,k)<=lim(u)

                   dp(u,k)=oo  dist(u,k)>lim(u)

    best(u)=min(dp(u,v))  

    其中v为u的子节点。

    代码如下:

    # include<iostream>
    # include<cstdio>
    # include<cstring>
    # include<vector>
    # include<queue>
    # include<list>
    # include<set>
    # include<map>
    # include<string>
    # include<cmath>
    # include<cstdlib>
    # include<algorithm>
    using namespace std;
    # define LL long long
    
    const int N=1005;
    const int INF=1000000000;
    
    struct Edge
    {
    	int to,nxt,w;
    };
    int cnt,n;
    int head[N];
    int dp[N][N];
    int best[N];
    int dis[N][N];
    int w[N],lim[N];
    Edge e[N<<1];
    
    void init()
    {
    	cnt=0;
    	memset(head,-1,sizeof(head));
    	for(int i=1;i<=n;++i){
    		best[i]=INF;
    		for(int j=1;j<=n;++j)
    			dp[i][j]=INF;
    	}
    }
    
    void add(int u,int v,int w)
    {
    	e[cnt].to=v;
    	e[cnt].w=w;
    	e[cnt].nxt=head[u];
    	head[u]=cnt++;
    }
    
    void read()
    {
    	scanf("%d",&n);
    	init();
    	for(int i=1;i<=n;++i)
    		scanf("%d",w+i);
    	for(int i=1;i<=n;++i)
    		scanf("%d",lim+i);
    	int a,b,c;
    	for(int i=1;i<n;++i){
    		scanf("%d%d%d",&a,&b,&c);
    		add(a,b,c);
    		add(b,a,c);
    	}
    }
    
    void getDis(int s,int u,int fa,int d)
    {
    	dis[s][u]=d;
    	for(int i=head[u];i!=-1;i=e[i].nxt){
    		int v=e[i].to;
    		if(v==fa) continue;
    		getDis(s,v,u,d+e[i].w);
    	}
    }
    
    void dfs(int u,int fa)
    {
    	for(int i=head[u];i!=-1;i=e[i].nxt){
    		int v=e[i].to;
    		if(v==fa) continue;
    		dfs(v,u);
    	}
    	for(int i=1;i<=n;++i){
    		if(lim[u]<dis[u][i]) continue;
    		dp[u][i]=w[i];
    		for(int j=head[u];j!=-1;j=e[j].nxt){
    			int v=e[j].to;
    			if(v==fa) continue;
    			dp[u][i]+=min(dp[v][i]-w[i],best[v]);
    		}
    		best[u]=min(best[u],dp[u][i]);
    	}
    }
    
    void solve()
    {
    	for(int i=1;i<=n;++i)
    		getDis(i,i,-1,0);	///找出任意两点之间的距离;
    	dfs(1,-1);
    	printf("%d
    ",best[1]);
    }
    
    int main()
    {
    	int T;
    	scanf("%d",&T);
    	while(T--)
    	{
    		read();
    		solve();
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    (转载)UITableView的详细讲解
    (转载)ios关闭虚拟键盘的几种方法
    (转载)NSTimer
    (转)FirstResponder 释放问题
    (转)IOS UITableView学习
    UITableView中的(NSIndexPath *)indexPath
    iOS开发UITableView基本使用方法总结1
    xcode快捷键的使用
    k8s1.13.0二进制部署-master节点(三)
    k8s1.13.0二进制部署-node节点(四)
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/5418566.html
Copyright © 2011-2022 走看看