您的位置:首页 > 其它

pat1053Path of Equal Weight (30)

2015-10-22 22:36 260 查看
题意分析:

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

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

判断策略如下:

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

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

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

可能坑点:

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

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

参考博客:/article/8560016.html

#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 105
vector<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;
}


可惜的是这种算法第二个测试案例没有过。原因暂时还没有找出来,希望知道的人告知一下
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: