【1079】Total Sales of Supply Chain (25 分)
1.题目
https://pintia.cn/problem-sets/994805342720868352/problems/994805388447170560 给出一棵树,求出叶子结点“带权路径”之和,这里不是以前那种带权,叶子结点真正的权值由该结点的深度决定(幂次方)——根结点处货物的价格为P,叶子结点的括号内数字表示货物数。
看懂题目的输入,每行开头为当前结点i的叶子结点个数,若该首数字非0,则该行后面的数字都为i结点的叶子结点数组下标(也就是题目直接给出结点的编号,且结点的编号一定是0、1、…N-1,N为结点个数——不需要newNode函数,因为题目中给定的编号可以直接作为Node数组的下标使用);而若该首数字为0,则该行后面的数字为叶结点的权值。
2.思路
DFS就对了,注意这题根结点的深度应设为0。
void DFS(int index,int depth){
if(Node[index].child.size()==0){//到达叶结点
ans+=Node[index].data*pow(1+r,depth);
return;
}
for(int i=0;i<Node[index].child.size();i++){
DFS(Node[index].child[i],depth+1);
}
}
3.完整代码
#include<vector>
#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<stdio.h>
#include<cmath>
using namespace std;
const int maxn=100010;
double ans=0,rate;
struct node{
double data;
vector<int> child;
}Node[maxn];
void DFS(int index,int depth){
if(Node[index].child.size()==0){
ans+=Node[index].data*pow(1+rate,depth);
return;
}
for(int i=0;i<Node[index].child.size();i++){
DFS(Node[index].child[i],depth+1);//递归访问子结点
}
}
int main(){
int n;
int num;
double price;
scanf("%d%lf%lf",&n,&price,&rate);
rate/=100;
for(int i=0;i<n;i++){
scanf("%d",&num);
if(num==0){
scanf("%lf",&Node[i].data);
}else{
for(int j=0;j<num;j++){
//scanf("%d",&Node[i].child[j]);
int child;
scanf("%d",&child);
Node[i].child.push_back(child);
}
}
}
DFS(0,0);
printf("%.1f\n",price*ans);
system("pause");
}
4.注意
(1)一开始OJ提示答案错误,后来发现是定义了全局变量rate
后,还在main函数里面重复定义了rate局部变量。
(2)注意scanf("%d",&Node[i].child[j])
这样写不对。
(3)题目给定的rate是百分数,因此要除以100,如样例的rate=1.00指1%。
【1090】Highest Price in Supply Chain (25 分)
1.题目
https://pintia.cn/problem-sets/994805342720868352/problems/994805376476626944
2.思路
和上一题类似,区别是这个要求所有叶结点中的最高价格(每层的货物价格会在父结点的价格上增加r%)和这个价格的叶结点总个数,也即【1090】的叶子结点的“初始”点权值是相同的,即只要计算深度最深的结点。
由于不用考虑结点的点权,可以不用设结构体结点了,而直接用vector<int>child[MAXV]
替代,每个child[i]都是一个vector,存放各个结点的所有子结点下标。
3.完整代码
#include<vector>
#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<stdio.h>
#include<cmath>
using namespace std;
const int maxn=100010;
int num=0;//最大深度的结点个数
vector<int>child[maxn];
int maxdepth=0;
double ans;
double rate,price;
void DFS(int index,int depth){
if(child[index].size()==0){
if(depth>maxdepth){//递归边界:到达叶结点
maxdepth=depth;
ans=price*pow(1+rate,maxdepth);
//printf("%lf\n",price);
num=1;//重置最大深度的结点个数为1
}else if(depth==maxdepth){
num++;
ans=price*pow(1+rate,maxdepth);//别漏了这句
}
return;
}
for(int i=0;i<child[index].size();i++){//注意判断的下标不是i
DFS(child[index][i],depth+1);
}
}
int main(){
int n,father,root;
scanf("%d%lf%lf",&n,&price,&rate);
rate/=100;
for(int i=0;i<n;i++){
scanf("%d",&father);
if(father!=-1)
//child[father][i]=i;
child[father].push_back(i);//i是father的子结点
else
root=i;
}
DFS(root,0);
printf("%.2f %d\n",ans,num);
system("pause");
}
4.注意
(1)根结点显然没有父结点,所以输入的第二行中遇到-1时的i即为root。
(2)题目给定的rate是百分数,因此要除以100,如样例的rate=1.00指1%。