pat1053Path of Equal Weight (30)

来源:互联网 发布:手机p照片软件 编辑:程序博客网 时间:2024/06/06 06:43

题意分析:

(1)给出一颗树的父子表示关系,给出每一个节点自身编号和节点权值,然后给出每一个非叶子结点及其子节点的邻接关系,然后找出一条路径使得路径上节点的权值之和等于给定的值,若有多条路径,则按照序列的大小关系输出,序列的大小关系指的是:序列a>序列b,则从序列a和序列b的第一个元素开始,第一次出现在同等位置上的a的元素大于b的元素

(2)使用DFS从根节点开始遍历,然后记录下当前的非叶子节点中权值最大的节点,并统计总权值,这样就能保证全局非递减序的输出。

判断策略如下:

①若当前总权值>给定值,则直接退出递归

②若当前总权值=给定值,且是叶子结点,则输出

③若当前总权值<给定值,且不是叶子结点,则找到其子节点中权值最大的节点,最为下一次递归的根节点

可能坑点:

(1)这题的难点在于如何对最后的多条路径输出结果按序输出,可以先存路径,然后再排序,也可以直接在DFS中采用“先大后小”的顺序递归。

(2)递归返回时记得需要将vector序列最后一个元素pop出去,以便进行下一次的操作

参考博客:http://blog.csdn.net/acm_ted/article/details/20801651

#include<cstdio>#include<cstring>#include<cmath>#include<string>#include<vector>#include<map>#include<set>#include<queue>#include<algorithm>using namespace std;#define INF 0x6fffffff#define MAX 105vector<int> link[MAX];vector<int> path;int weight[MAX];bool flag[MAX];int n,m,s;void dfs(int weit,int idx){    int len;    weit+=weight[idx];    if(weit>s) return;//如果权重和大于要求,返回    else if(weit==s&&link[idx].size()==0)    {//如果权重和等于要求且当前结点无子树        path.push_back(weight[idx]);        printf("%d",path[0]);        len=path.size();        for(int i=1;i<len;++i)            printf(" %d",path[i]);        printf("\n");        path.pop_back();    }    else if(weit<s&&link[idx].size()>0)    {        int maxm,maxIdx=0;        path.push_back(weight[idx]);        for(;maxIdx!=-1;)        {            maxm=maxIdx=-1;            len=link[idx].size();            for(int i=0;i<len;++i)            {                if(flag[link[idx][i]]==false&&weight[link[idx][i]]>maxm)                {                    maxIdx=link[idx][i];                    maxm=weight[link[idx][i]];                }            }            if(maxIdx!=-1)            {                flag[maxIdx]=true;                dfs(weit,maxIdx);            }        }        flag[idx]=true;        path.pop_back();    }    return;}int main(){    int a,b,k;    scanf("%d%d%d",&n,&m,&s);    memset(flag,false,sizeof(flag));    for(int i=0;i<n;++i)        scanf("%d",weight+i);    for(int i=0;i<m;++i)    {        scanf("%d%d",&a,&k);        for(int j=0;j<k;++j)        {            scanf("%d",&b);            link[a].push_back(b);        }    }    dfs(0,0);    return 0;}

解法二:思路和以上有一处不一样,不是采用DFS,而是直接采用树的父子关系这个特性,每次输入新的子节点时,记录其当前的总权值=父节点的总权值+子节点权值,然后遍历所有的子节点,查看其总权值是否等于给定值,最后对多个序列排序

#include <iostream>#include <stdio.h>#include <string.h>#include <algorithm>#include <vector>using namespace std;vector<int>path[101];int total[101],weights[101],father[101]={-1};bool isLeaf[101];bool cmp(vector<int>a,vector<int>b){    for(int i=0;i<a.size()&&i<b.size();i++)    {        if(a[i]!=b[i])return a[i]>b[i];    }}int main(){    int N,M,S;    scanf("%d%d%d",&N,&M,&S);    int non_Leaf,childNum,child;    for(int i=0;i<N;i++)scanf("%d",weights+i);    father[0]=0;    total[0]=weights[0];    memset(isLeaf,1,sizeof(isLeaf));    for(int j=0;j<M;j++)    {        scanf("%d%d",&non_Leaf,&childNum);        isLeaf[non_Leaf]=0;        for(int k=0;k<childNum;k++)        {            scanf("%d",&child);            father[child]=non_Leaf;            total[child]=total[non_Leaf]+weights[child];        }    }    int index=0;    for(int i=0;i<N;i++)    {        int paraent=i;        if(isLeaf[i]&&total[i]==S)        {            while(paraent!=0)            {                path[index].push_back(weights[paraent]);                paraent=father[paraent];            }            path[index].push_back(weights[0]);            reverse(path[index].begin(),path[index].end());            index++;        }    }    sort(&path[0],&path[index],cmp);    for(int i=0;i<index;i++)    {        int first=1;        for(int j=0;j<path[i].size();j++)        {            if(first)first=0;            else printf(" ");            printf("%d",path[i][j]);        }        printf("\n");    }    return 0;}

可惜的是这种算法第二个测试案例没有过。原因暂时还没有找出来,希望知道的人告知一下


0 0
原创粉丝点击