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
- pat1053Path of Equal Weight (30)
- 1053. Path of Equal Weight (30)
- 1053. Path of Equal Weight (30)-PAT
- 1053. Path of Equal Weight (30)
- 1053. Path of Equal Weight (30)
- PAT 1053. Path of Equal Weight (30)
- 1053. Path of Equal Weight (30)
- 1053. Path of Equal Weight (30)
- 1053. Path of Equal Weight (30)
- 1053. Path of Equal Weight (30)
- PAT 1053. Path of Equal Weight (30)
- 1053. Path of Equal Weight (30)
- 1053. Path of Equal Weight (30)
- 1053. Path of Equal Weight (30)
- 1053. Path of Equal Weight (30)
- PAT 1053. Path of Equal Weight (30)
- 1053. Path of Equal Weight (30)
- 1053. Path of Equal Weight (30)
- 关于枚举的一种用法
- opencv perspectiveTransform
- Quartz使用-入门使用(java定时任务实现)
- iOS经典讲解之Swift分支结构与循环详解
- ORACLE 常用函数——日期/时间函数
- pat1053Path of Equal Weight (30)
- 关于spring
- JVM的内存区域划分
- [每日一答] [20151022] 使用MySQL命令行修改密码
- 配置 log4j
- POJ3624 Charm Bracelet
- hibernate一对多以非主外键字段做级联
- 《设计模式》之简单工厂模式
- iOS开发-数据持久化