最短最优升级路径(完美世界2017秋招真题)

题目说明:

游戏网站提供若干升级补丁,每个补丁大小不一,玩家要升级到最新版,如何选择下载哪些补丁下载量最小。

输入

第一行输入              第一个数为用户版本  第二个数为最新版本,空格分开

接着输入N行补丁数据        第一个数补丁开始版本 第二个数为补丁结束版本 第三个数为补丁大小,空格分开

输出

对于每个测试实例,输出一个升级路径以及最后实际升级的大小

时间限制

C/C++语言:1000MS

其他语言:3000MS

样例输入

1000 1050

1000 1020 50

1000 1030 70

1020 1030 15

1020 1040 30

1030 1050 40

1040 1050 20

样例输出

1000->1020->1040->1050(100)

思路:

本题自己想到的是Dijkstra算法.

设给定的旧版本好为o,要求的最新版本为n;

考虑有一个集合S={},它保存从o到其他更新的版本的最少补丁大小的下载顺序和补丁的实际大小。

接着讲起始集合o添加到S中,

然后遍历给定的集合,找到更新的起始版本在S集合中、更新后的版本不在S集合中且补丁最小(这里的最小是从o出发到它更新后的版本的补丁之和的最小)的更新组合,找到后,将它加入集合S;

循环上面一步,知道找到o到n的最小更新方法。

用公式表示

起始状态:S={o}

假设其他版本分别是V={a b c d e f n}(相当于图的点集),可更新的方法用集合E(相当于图的边集)表示E={ev(ab),ev(bc),...};其中ev(ab)表示从a版本更新到b版本需要下载ev大小的补丁。

每次找满足下面条件的更新方法:

若ev(st)∈E,s∈S,t?S,minev(ot) = min{ev(ot),ev(os) + ev(st)} = ev(os) + ev(st);则将t加入S集合。

 1 #include<iostream>
 2 #include<vector>
 3
 4 using namespace std;
 5
 6 pair<int,vector<int>> minPatch(vector<int> &oldVersion, vector<int> &newVersion, vector<int> &patch, int start, int end){
 7     //pair的第一个参数是该最小补丁的大小,第二个参数是start到底i个补丁的最小时的下载线路
 8     vector<pair<int,vector<int>>> minPatch;
 9     vector<int>fv;
10     fv.push_back(start);
11     pair<int, vector<int>>first(0, fv);
12     minPatch.push_back(first);
13     while (true){
14         int curMin = -1, curIndex,minIndex = -1;//minIndex保存当起始版本不是start时,其在minPatch中的位置
15         int len, pos;//如果起始版本在minPatch中存在,pos记录其位置
16         for (int i = 0; i < oldVersion.size(); i++){
17             //标记当前补丁路线中的起始版本和最新版本是否在minPatch中已存在
18             //只有起始版本存在而最新版本不存在时,才合法
19             bool firFlag = false, secFlag = true;
20             //查找当前补丁路线中的目标版本是否已经在minPatch中
21             for (int j = 0; j < minPatch.size(); j++){
22                 len = minPatch.at(j).second.size() - 1;
23                 //检验当前补丁路线中的起始版本是否在minPatch中已存在
24                 if (oldVersion.at(i) == minPatch.at(j).second.at(len)){
25                     firFlag = true;
26                     pos = j;
27                 }
28                 if (newVersion.at(i) == minPatch.at(j).second.at(len))secFlag = false;//检验当前补丁路线中的最新版本是否在minPatch中已存在
29             }
30             if (firFlag && secFlag){
31                 int p = minPatch.at(pos).first + patch.at(i);
32                 if (curMin < 0 || p < curMin){//找到最小的合法新补丁
33                     curMin = p;
34                     curIndex = i;
35                     minIndex = pos;
36                 }
37             }
38         }
39         //添加新补丁进minPatch
40         pair<int, vector<int>>cur;
41         vector<int> curPatch(minPatch.at(minIndex).second);
42         curPatch.push_back(newVersion.at(curIndex));
43         cur.first = minPatch.at(minIndex).first + patch.at(curIndex);
44         cur.second = curPatch;
45         if (newVersion.at(curIndex) == end){
46             return cur;
47         }
48         minPatch.push_back(cur);
49     }
50     return minPatch.at(minPatch.size() - 1);
51 }
52
53 int main(){
54   vector<int>oldV,newV,patch;
55   int start,end;
56   cin>>start>>end;
57   int o,n,p;
58   while(cin >>o >> n >> p){
59       oldV.push_back(o);
60     newV.push_back(n);
61     patch.push_back(p);
62   }
63   pair<int,vector<int>> paths = minPatch(oldV,newV,patch,start,end);
64   vector<int>::iterator it = paths.second.begin();
65   while(it != paths.second.end()){
66       cout << (*it);
67     ++it;
68     if(it != paths.second.end()) cout<< "->";
69   }
70   cout << "(" << paths.first <<")";
71     return 0;
72 }
时间: 2024-10-04 22:53:33

最短最优升级路径(完美世界2017秋招真题)的相关文章

进制均值(京东2017秋招真题)

思路:利用取余数方法可以得到转换进制之后数字表示的所有位数,本题只求和的平均值,可以不严格       考虑正排列或者逆排列 之后使用fractions的Fraction函数,方便满足需要的分数格式要求 语句:fractions的Fraction函数  Fraction(a,b)中a表示分子,b表示分母 python代码: # -*- coding: utf-8 -*- import fractions as f while 1:     number=[]     a=int(raw_inpu

采购单(京东2017秋招真题)

本来也不算很难的一道题,但是总是只通过60% 或者 80% 一眼就看出思路,代码也不难的题就是不能全部通过也是神烦,应该是格式上的问题,也不算完全弄明白了,简单说说,作为一种经验. 思路:给价钱 和 每种物品的个数排序 最贵:最高价买最多的物品,累加 最低:最低价买最多的物品.累加 语句:list.count()    list.sort()    set(list)等 以下为正确的python语句 while 1:     r = raw_input()     if r != '':    

集合(京东2017秋招真题)

解答思路很简单,使用Python的set函数和sort函数就可以完成,但是做完之后有时候有错误 如图 明明使用了sort但没有排序 原来是因为读入之后数字是字符串格式,所以排序的时候15 就排在了 6的前面 使用 int 调整一遍列表中元素的类型就可以了 while 1:     (x,y)=(int(x) for x in raw_input().split())     ary1=raw_input().split()     ary2=raw_input().split()     ary

第K个幸运数(京东2017秋招真题)

题目 4和7是两个幸运数字,我们定义,十进制表示中,每一位只有4和7两个数的正整数都是幸运数字.前几个幸运数字为:4,7,44,47,74,77,444,447... 现在输入一个数字K,输出第K个幸运数. 输入 第一行一个数字T(T<=1000)表示测试数据的组数.对于每组测试数据,输出一个数K(1 <= K <= 100000000000000000000000000) 思路 只有四和7,而且还和顺序有关,4,7,44,47,74,77 ,不免想到二进制0,1,00,01,10,11

网易2017秋招编程题集合-牛客网

网易2017秋招编程题集合-牛客网 链接:https://www.nowcoder.com/questionTerminal/0147cbd790724bc9ae0b779aaf7c5b50来源:牛客网 如果一个数字序列逆置之后跟原序列是一样的就称这样的数字序列为回文序列.例如: {1, 2, 1}, {15, 78, 78, 15} , {112} 是回文序列, {1, 2, 2}, {15, 78, 87, 51} ,{112, 2, 11} 不是回文序列. 现在给出一个数字序列,允许使用一

网易2017秋招编程题——回文序列 解题报告

Problem:https://www.nowcoder.com/question/next?pid=2811407&qid=46573&tid=6015849 如果一个数字序列逆置之后跟原序列是一样的就称这样的数字序列为回文序列.例如: {1, 2, 1}, {15, 78, 78, 15} , {112} 是回文序列, {1, 2, 2}, {15, 78, 87, 51} ,{112, 2, 11} 不是回文序列. 现在给出一个数字序列,允许使用一种转换操作: 选择任意两个相邻的数,

网易2017秋招编程题集合_以下代码全部来自牛客网

如果一个数字序列逆置之后跟原序列是一样的就称这样的数字序列为回文序列.例如:{1, 2, 1}, {15, 78, 78, 15} , {112} 是回文序列, {1, 2, 2}, {15, 78, 87, 51} ,{112, 2, 11} 不是回文序列.现在给出一个数字序列,允许使用一种转换操作:选择任意两个相邻的数,然后从序列移除这两个数,并用这两个数字的和插入到这两个数之前的位置(只插入一个和).现在对于所给序列要求出最少需要多少次操作可以将其变成回文序列. 链接:https://ww

运维工程师笔试真题:美团点评 2017 春招真题

1.数据库索引可以明显提高哪一操作的效率?正确答案: A A SELECTB INSERT INTO - VALUES -C UPDATED DELETE 2.数据库:以下哪种锁定方式能提供最佳的并行访问性能?正确答案: D A 列锁定B 表锁定C 块锁定D 行锁定 3.从DELETE 语句中省略WHERE 子句,将产生什么结果?正确答案: B A DELETE 语句将失败因为没有记录可删除B DELETE 语句将从表中删除所有的记录C DELETE 语句将提示用户进入删除的标准D DELETE

算法是什么我记不住,But i do it my way. 解一道滴滴出行秋招编程题。

只因在今日头条刷到一篇文章,我就这样伤害我自己,手贱. 刷头条看到一篇文章写的滴滴出行2017秋招编程题,后来发现原文在这里http://www.cnblogs.com/SHERO-Vae/p/5882357.html.看了下,挺有意思,于是就想了想,又写了写,最终撸出来了.刚开始一看顿时感觉很熟悉,大学数据结构和算法课肯定讲过相关东西,什么深度搜索,广度搜索,最优路径,最优解...但是现在你让我说个一二三,我还就只记住几个名字,说不定名字都记错.我向来不喜欢死记东西,能查到的真的不想背下来,而