zoukankan      html  css  js  c++  java
  • HDU-4003 Find Metal Mineral (树形DP+分组背包)

    题目大意:用m个机器人去遍历有n个节点的有根树,边权代表一个机器人通过这条边的代价,求最小代价。

    题目分析:定义状态dp(root,k)表示最终遍历完成后以root为根节点的子树中有k个机器人时产生的总代价。则状态转移方程为:

    dp(root,k)=min(dp(root,k),dp(son,j)+dp(root,k-j)+j*w(root,son))  j>0

    要注意,当j为0的时候表示遍历完son这个子树后所有的机器人都回到root。可以证明,如果让遍历son的所有的机器人都回到root,那么遍历son的机器人越多,产生的代价就越高。

    代码如下:

    # include<iostream>
    # include<cstdio>
    # include<cstring>
    # include<algorithm>
    using namespace std;
    # define LL long long
    
    const int N=10005;
    
    struct Edge
    {
    	int to,w,nxt;
    };
    Edge e[N<<1];
    
    int head[N];
    int cnt,n,s,m;
    int dp[N][12];
    
    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 init()
    {
    	int a,b,w;
    	cnt=0;
    	memset(dp,0,sizeof(dp));
    	memset(head,-1,sizeof(head));
    	for(int i=1;i<n;++i){
    		scanf("%d%d%d",&a,&b,&w);
    		add(a,b,w);
    		add(b,a,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 j=m;j>=0;--j){
    			dp[u][j]+=dp[v][0]+2*e[i].w;
    			for(int k=1;k<=j;++k)
    				dp[u][j]=min(dp[u][j],dp[u][j-k]+dp[v][k]+k*e[i].w);
    		}
    	}
    }
    
    void solve()
    {
    	dfs(s,-1);
    	printf("%d
    ",dp[s][m]);
    }
    
    int main()
    {
    	while(~scanf("%d%d%d",&n,&s,&m))
    	{
    		init();
    		solve();
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    c++11 static_assert
    UVA
    析构函数与运行错误
    UVA
    2017 ACM-ICPC 亚洲区(乌鲁木齐赛区) C. Coconut
    2017 ACM-ICPC 亚洲区(乌鲁木齐赛区) A. Banana
    DOCTYPE的作用?
    数组去重的方法
    闭包的分析?
    SVN(集中式管理)分析
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/5351382.html
Copyright © 2011-2022 走看看