• 「CJOJ2366」机器人采集金属


    Description


    人类在火星上发现了一种新的金属! 这些金属分布在一些奇怪的地方, 不妨叫它节点好 了。 一些节点之间有道路相连, 所有的节点和道路形成了一棵树。 一共有 n 个节点, 这些 节点被编号为 1~n 。 人类将 k 个机器人送上了火星, 目的是采集这些金属。 这些机器人都 被送到了一个指定的着落点, S 号节点。 每个机器人在着落之后, 必须沿着道路行走。 当 机器人到达一个节点时, 它会采集这个节点蕴藏的所有金属矿。
    当机器人完成自己的任务之后, 可以从任意一个节点返回地球。 当然, 回到地球的机器 人就无法再到火星去了。 我们已经提前测量出了每条道路的信息, 包括它的两个端点 x 和 y, 以及通过这条道路需要花费的能量 w 。 我们想花费尽量少的能量采集所有节点的金属, 这 个任务就交给你了。

    Input


    第一行包含三个整数 n, S 和 k , 分别代表节点个数、 着落点编号, 和机器人个数。
    接下来一共 n-1 行, 每行描述一条道路。 一行含有三个整数 x, y 和 v , 代表在 x 号 节点和 y 号节点之间有一条道路, 通过需要花费 v 个单位的能量。 所有道路都可以双向 通行。

    Output


    输出一个整数, 代表采集所有节点的金属所需要的最少能量。

    Hint


    样例2解释:

    所有机器人在 1 号节点着陆。
    第一个机器人的行走路径为 1->6 , 在 6 号节点返回地球, 花费能量为 1000。
    第二个机器人的行走路径为 1->2->3->2->4 , 在 4 号节点返回地球, 花费能量为 1003。
    第一个机器人的行走路径为 1->2->5 , 在 5 号节点返回地球, 花费能量为 1001。

    数据范围:

    对于5%的数据,(n≤20,k≤10)
    对于另外5%的数据,(n≤100,k≤3)
    对于另外5%的数据,(v=1)
    对于另外5%的数据,所有边的v值相等
    对于另外10%的数据,树形成了一条链
    对于另外10%的数据,(k=1)
    对于另外20%的数据,(n≤1000,k≤10)
    对于全部的数据,(1≤n≤5∗10^4,1≤k≤20,0≤v≤10^4)

    题解


    对于每一个点i,我们都可以令(dp[i][j])表示以(i)为根节点的子树,消耗(j)个机器人的最小能耗。消耗在这里的意思表示直接让它回地球。。。
    然后就可以很简单的列出DP方程,就是一个树形DP的模板(雾)

    #include<stdio.h>
    #include<stdlib.h>
    inline int gi(){
    	int f=1,sum=0;char ch=getchar();
    	while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
    	return f*sum;
    }
    const int maxn=50000+10,maxk=20+10;
    struct node{
    	int to,nxt,w;
    }e[maxn<<1];
    int front[maxn],cnt;
    void Add(int u,int v,int w){
    	e[++cnt].to=v;e[cnt].nxt=front[u];
    	e[cnt].w=w;front[u]=cnt;
    }
    int dp[maxn][maxk],k;
    int min(int a,int b){
    	return a>b?b:a;
    }
    void dfs(int u,int fa){
    	for(int i=front[u];i;i=e[i].nxt){
    		int v=e[i].to;
    		if(v==fa)continue;
    		dfs(v,u);
    		for(int j=k;j>=0;j--){
    			dp[u][j]+=dp[v][0]+2*e[i].w;
    			for(int p=1;p<=j;p++)
    				dp[u][j]=min(dp[u][j],dp[u][j-p]+dp[v][p]+p*e[i].w);
    		}
    	}
    }
    int main(){
    	int i,j,n,m,sum=0,S;
    	n=gi();S=gi();k=gi();
    	for(i=1;i<n;i++){
    		int x=gi(),y=gi(),w=gi();
    		Add(x,y,w);Add(y,x,w);
    		sum+=w;
    	}
    	dfs(S,S);
    	printf("%d
    ",dp[S][k]);
    	return 0;
    }
    
  • 相关阅读:
    利用XAF中的FeatureCenter例子的,直接打开DetailView
    XAF 应用程序模型基础[转]
    XAF 如何给記錄增加版本控制?
    Simpler way to Create a Custom User Control
    建议将小川同志免费租借给欧洲用30年[转]文/端宏斌
    第六集 MSF构思阶段项目团队的组建
    MS_HotFix
    C#域内远程机文件信息注册表访问。
    访问 远程机 盘符 设置
    Silk_ 运行时_控件_属性_捕捉.
  • 原文地址:https://www.cnblogs.com/cjgjh/p/9354838.html
Copyright © 2020-2023  润新知