zoukankan      html  css  js  c++  java
  • 洛谷P2015 二叉苹果树

    题面:

    有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点)

    这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1。

    我们用一根树枝两端连接的结点的编号来描述一根树枝的位置。下面是一颗有4个树枝的树

    2   5
      / 
      3   4
        /
        1
    

    现在这颗树枝条太多了,需要剪枝。但是一些树枝上长有苹果。

    给定需要保留的树枝数量,求出最多能留住多少苹果。

    输入输出格式

    输入格式:

    第1行2个数,NNQ(1<=Q<=N,1<N<=200)Q(1<=Q<= N,1<N<=200)

    N表示树的结点数,Q表示要保留的树枝数量。接下来N1N-1行描述树枝的信息。

    每行3个整数,前两个是它连接的结点的编号。第3个数是这根树枝上苹果的数量。

    每根树枝上的苹果不超过30000个。

    输出格式:

    一个数,最多能留住的苹果的数量。

    输入输出样例

    输入样例

    5 2
    1 3 1
    1 4 10
    2 3 20
    3 5 20
    

    输出样例

    21
    

    分析:

    f[i][j]f[i][j] 表⽰以i节点为根,保留j个树枝最多留下
    多少个苹果。
    只给左⼉⼦:f[i][j]=f[lson[i]][j1]+vlson[i]f[i][j]=f[lson[i]][j-1]+vlson[i]
    只给右⼉⼦:f[i][j]=f[rson[i]][j1]+vrson[i]f[i][j]=f[rson[i]][j-1]+vrson[i]
    都分⼀点:f[i][j]=max(f[lson[i]][k]+f[rson[i]][jk2]+vlson[i],vrson[i]).0<=k<=j2f[i][j]=max(f[lson[i]][k]+f[rson[i]][j-k-2]+vlson[i],vrson[i]). 0<=k<=j-2.

    另种思路在代码中说明

    code:(搜索+dp)

    #include<cstdio>
    #include<cmath>
    using namespace std;
    int n,q;
    struct ben
    {
    	int to,last,val,dq;//to记录这条边的终点,last记录上一条边,dq记录边的起点,val记录边的权值
    }a[205];
    int f[205][205];
    int cnt=1;
    int head[205];//head[i]表示以i为起点的边的编号
    void add(int x,int y,int num)//连边函数
    {
    	a[cnt].to=y;
        a[cnt].last=head[x];
        a[cnt].dq=x;
        a[cnt].val=num;
        head[x]=cnt;
        cnt++;
    }
    void search(int dq,int father)
    {
    	for(int i=head[dq];i!=-1;i=a[i].last)
    	{
    		int b=a[i].to;//找到这条边的终点
    		if(b==father)continue;//不能为起点
    		f[b][1]=a[i].val;//初始化
    		search(b,dq);//搜索
    		for(int j=q;j>=1;j--)
    		{
    			for(int k=0;k<=j;k++)
    			{
    				if((j!=1&&j!=k)||dq==1)
    				{
    					f[dq][j]=fmax(f[dq][j],f[b][k]+f[dq][j-k]);//枚举中间点k,得出方程
    				}
    			}
    		}
    	}
    }
    int main()
    {
    	
    	scanf("%d%d",&n,&q);
    	for(int i=1;i<=n;i++)
    	{
    		head[i]=-1;
    	}//初始化
    	for(int i=1;i<n;i++)
    	{
    		int x,y,num;
    		scanf("%d%d%d",&x,&y,&num);
    		add(x,y,num);
    		add(y,x,num);//注意要连双向边
    	}
    	search(1,0);
    	printf("%d",f[1][q]);
    	return 0;
    }
    
  • 相关阅读:
    判断有无网络
    Listview的OnScrollListener的滑动监听实现分页加载
    第三方 XListview 上拉加载、下拉刷新、分页加载和Gson解析
    Gson解析数据
    百度地图实现普通地图、定位、周边搜索功能
    Viewpager实现网络图片的轮播
    英语wacche腕表
    caement Archaic spelling of cement
    水泥caement单词
    英语caement水泥
  • 原文地址:https://www.cnblogs.com/vercont/p/10210091.html
Copyright © 2011-2022 走看看