您的位置:首页 > 其它

CCF 2017年12月第5题-商路

2018-03-05 16:58 211 查看
这一题题目很长,但理解起来并不困难。有一点很重要,那就是题目输入的顺序是城市编号的顺序,而城市编号的顺序又直接决定了城市之间的上下级关系。虽然编号小的不一定是大编号的下级,但下级城市的编号一定比上级城市的编号小,如何利用这一点非常重要。假如城市A的下级城市是B,C,D ;那如果B,C,D 本身的商路价值都是最大话之后,A 只能在B,C,D 中挑选一个与之相连,或者不相连,来使自己的商路价值最大话。也就是如果B,C,D的商路价值都是已知的了,那A 的商路价值就都是已知的了。 如此以来,只需要按照逆序从后向前分别计算商路的最大值就可以了。比如题中所给的第一个例子: 开始时假设所有城市的商路最大价值都是0, 这时最后一个城市的商路价值就是真实的了,随后以此找它的上级城市(不一定时直接上级),判断上级城市与最后一个城市相连会不会让它的商路价值增加就可以了,当处理到首都之后就可以处理倒数第二个城市了。估算一下算法复杂度, 首先扫描一遍至少是 N , 然后每一个城市要处理它的上级,是完美二叉树的话,那每个城市的上级应该是log i , 如果所有城市排成一条线的话那每个城市的上下级就是 i-1 了,这样最好的情况下复杂度是NlogN 最差的情况是 N^2 看起来还可以接受。按照这个思路写一份代码提交试试看:

// 20171203-商路问题.cpp: 定义控制台应用程序的入口点。
//

#include "stdafx.h"
/*先对数据进行分层,数据输入时统计每个结点到首都的距离(跳数),随后对点进行排序,从低到高计算*/
#include<iostream>
#include<set>
#include<vector>
using namespace std;
struct city {
long long pre;
int len;
long long v;
long long f;
};
int main()
{
int T; cin >> T;
for (int i = 0; i < T; ++i)
{
int n;
cin >> n;
struct city * Citys = new struct city[n + 1];
long long * Values = new long long[n + 1];
for (int i = 1; i <= n; ++i)
{
cin >> Citys[i].pre; cin >> Citys[i].len; cin >> Citys[i].v; cin >> Citys[i].f;
Values[i] = 0;
}
/*从后向前逆向扫描*/
long long pre;
long long lens;
long long Nvalue;
long long Mvalue;
for (long long i = n; i > 0; --i)
{
/*如果由该点连向前驱的商路能够增加前驱的商路价值,前驱的商路就选择改道*/
pre = Citys[i].pre;
lens=Citys[i].len;
while (pre>=1)
{
Mvalue = Values[i] + Citys[pre].v;
if (Values[pre] < Mvalue)
{

Nvalue = Mvalue - (Citys[pre].f - lens)*(Citys[pre].f - lens);//几乎可以认定这一步是最耗时的一步,所以这里尽力优化
}
lens += Citys[pre].len;
pre = Citys[pre].pre;
}

}
long long sum = 0;
for (long long i = 1; i <= n; ++i)
{
sum += (Values[i]%1000000000000000000)%1000000000000000000;
}
cout << sum<<endl;
}

return 0;
}
只有60分,不够高效;应该是一字型的无法通过。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  CCF