|给出路径长度(点权和)求|1053 Path of Equal Weight (30分)*********

在这里插入图片描述1053 Path of Equal Weight (30分)

//给定一棵树和每个节点的权值
//求所有从根节点到叶子节点的路径
//使得每条路径上的节点的权值之和等于给定的常数S

//如果有多条这样的路径
//按照路径非递增的顺序输出
//其中路径的大小是指,如果有两条路径分别为a1->a2->...ai->an和b1->b2->b3->...bi->bm
//如果ak>bk,则称第一条路径大------>递减,编号大的先输出
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;

struct node{
    
    
    int w;
    vector<int> child;
}Node[110];

int n,m,S;
int path[110];//记录路径

void dfs(int index,int depth,int sum){
    
    
    if(sum>S)return;
    if(sum==S){
    
    //当前sum和为s
        if(Node[index].child.size()!=0)return;//还没到达叶子节点,直接返回
        //到达了叶子节点,此时path[]中存放了一条完整的路径,输出它
        else{
    
    
            for(int i=0;i<depth;i++){
    
    
                printf("%d",Node[path[i]].w);//
                if(i<depth-1)printf(" ");
                else printf("\n");
        } 
        return ;
    } 
   
 }
    for(int i=0;i<Node[index].child.size();i++){
    
    
        int child=Node[index].child[i];//节点index的第i个子节点的编号--孩子编号
        path[depth]=child;//path下标从0开始,层数从1开始,下标是层数,元素是下一个要遍历的孩子编号
        dfs(child,depth+1,sum+Node[child].w);
    }
   
    
    
}

bool cmp(int a,int b){
    
    
    return Node[a].w>Node[b].w;//将某一节点的孩子节点,按节点的点权从大到小排序
}


int main()
{
    
    
    scanf("%d%d%d",&n,&m,&S);
    for(int i=0;i<n;i++){
    
    
        scanf("%d",&Node[i].w);
    }
    int id_father,num_child,id_child;
    for(int i=0;i<m;i++){
    
    
        cin>>id_father>>num_child;
        for(int j=0;j<num_child;j++){
    
    
            cin>>id_child;
            Node[id_father].child.push_back(id_child);
        }
        sort(Node[id_father].child.begin(),Node[id_father].child.end(),cmp);//排序  //  ?????????按节点的点权从大到小排序,默认是升序,从小到大,所以需要重写cmp
    }
    path[0]=0;//路径的第一个节点设置为0号节点,因为我们求的是从根节点到孩子节点的路径
    dfs(0,1,Node[0].w);//根节点是0,在第一层(Ai---A1,A2....),路径总权重是10
    
    return 0;
}
--------------
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;

struct node{
    
    
    int w;//点权
    vector<int> child;//孩子节点
}Node[110];

int n,m,s;
int path[110];//记录路径

void dfs(int index,int depth,int sum){
    
    //我们要求从根节点到叶子节点的路径长度为s的方案
    if(sum>s)return;
    if(sum==s){
    
    
        if(Node[index].child.size()!=0)return;//路径的长度到了s,但是没有路要走,没到达孩子节点,不符合题意,去掉
        else{
    
    //到达了孩子节点并且路径长度为s,是我们要求的
            for(int i=0;i<depth;i++){
    
    
                printf("%d",Node[path[i]].w);      //  path[depth]=child;
                if(i<depth-1)printf(" ");
                else printf("\n");
            }
            return;
        }
        
    }
    //sum<s//还没到达规定的路径长度,继续递归找孩子
    for(int i=0;i<Node[index].child.size();i++){
    
    //有几个孩子
        int child=Node[index].child[i];//第几个孩子
        path[depth]=child;
        dfs(child,depth+1,sum+Node[child].w);
    }
}

bool cmp(int a,int b){
    
    //a,b都是某个节点的孩子的编号//对某一结点的孩子节点,按照点权大小排序
//10 5 2 7
//10 4 10
// scanf("%d",&Node[i].w);//输入每个节点的点权--结构体
    return Node[a].w>Node[b].w;
}


int main()
{
    
    
    
    scanf("%d%d%d",&n,&m,&s);//20 9 24
    for(int i=0;i<n;i++){
    
    //节点编号从0开始,i代表节点编号
        scanf("%d",&Node[i].w);//输入每个节点的点权--结构体
    }
    int id_father,num_child,id_child;
    for(int i=0;i<m;i++){
    
    //给出有孩子节点的节点的信息----编号要用id_father
        cin>>id_father>>num_child;
        for(int j=0;j<num_child;j++){
    
    //孩子的个数....孩子的点权
            cin>>id_child;//00 4
            Node[id_father].child.push_back(id_child);//01 02 03 04
        }
        sort(Node[id_father].child.begin(),Node[id_father].child.end(),cmp);//04 03 02 01
    }
    path[0]=0;
    dfs(0,1,Node[0].w);//根节点编号,路径的下标(A1,A2..),总权重(现在仅仅只有根节点的点权)
    return 0;
}

这道题dfs遍历树,和以往做的题目不太一样,传入了sum这个形参,这是由于题目而调整的
因此递归条件也和sum这个参数有关

这个题目让我想到了一道题—背包,因为背包也是传入多个参数,而且那些参数,我都不太懂,所以来分析一下

例子:背包价值最大

//有n件物品,每件物品的重量是w[i],价值是c[i],现需要选出若干物品放入一个容量为V的背包里,
//使的在选入背包的物品重量和不超过容量v的前提下,让背包物品的价值之和最大,求最大价值(1<=n<=20)
void DFS(int index,int sumW,int sumC)
//有n件物品,每件物品的重量是w[i],价值是c[i],现需要选出若干物品放入一个容量为V的背包里,
//使的在选入背包的物品重量和不超过容量v的前提下,让背包物品的价值之和最大,求最大价值(1<=n<=20)

//输入数据:
//5 8//5件物品,背包容量为8
//3 5 1 2 2 //重量分别是3 5 1 2 2
//4 5 2 1 3//价值分别是4 5 2 1 3

//输出结果
//10
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn=50;

int n,v,maxSumW=0;//物品件数n,背包容量v
int w[maxn],c[maxn];//w[i]为每一件物品的重量,c[i]为每一件物品的价值

void dfs(int index,int sumW,int sumC){
    
    
    
    // if(sumW>v)return;
    // else if(sumW==v){
    
    
        
    // }
    if(index==n){
    
    //每次都要对物品进行选择,选择最佳方案
        if(sumW<=v&&sumC>maxSumW)
            maxSumW=sumC;
        return;
    }
    
    dfs(index+1,sumW,sumC);
    dfs(index+1,sumW+w[index],sumC+c[index]);
}

int main()
{
    
    
    scanf("%d%d",&n,&v);
    for(int i=0;i<n;i++){
    
    
        scanf("%d",&w[i]);//每件物品的重量
    }
    for(int i=0;i<n;i++){
    
    
        scanf("%d",&c[i]);
    }
    
    dfs(0,0,0);//初始化为第0件物品,当前总重量和总价值均为0
    printf("%d",maxSumW);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44769957/article/details/109076200