华为2018笔试 5.9 号 最后一题 关于 图的最短路径问题

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

读懂题目

第一张图片: 
             1.知道各个路段的长度范围;(用于后边的条件检测,即判断当前输入是否产生异常)
第二张图片:   1.知道各个路段的时速,用来记录后面的过路费,其实只有当100时候有用,其余都是废话,(但是是否需要考虑有可能有时速超过100的情况并没有从测试用例得知)     

第三张图片:   告知约束函数,即最终代价与速度其实关系不大,仅仅与过滤费有关;

解题

首先读懂题目的一瞬间知道这个题目必用图的最短路径方法来解,稍微了解图的都应该知道,并且由最终的测试用例知道是求起始到结束点的特定点,所以使用较为简单的迪杰特斯拉算法解;
   1.整个题目可以大致划分为如下三块:

第一块:
处理测试输入,将对应的诸如1,2,3,60;…这样的输入转化为我们所需要的int形式的输入,并在输入中做检测是否存在不符合条件的输入比如每一组的第一个 与 第二个输入是否在1-1000之间,
第二,第三个与第四个参数是否也在特定的范围之间;
代码如下:(没有对相应的参数范围做检测)可以自行添加;

 //其中input为输入字符串,temp用来存储转换后的整形输入;
   temp:   temp[n][4];  //n与分号的个数有关;
 void Process(string& input,int** temp){
  int len = input.size();
  int num = 0;
  int pos = 0,level = 0;
  int i = 0, j=0;
  for(i=0; i<len;){
    if(input[i] == ';'){//这里还需要判断level
      level++;
      pos = 0;
      i = i+1; //知道起始位置了;
      continue;
    }
    else{
      num = 0;
      if(pos <= 2){  //pay attention
        for(j=i; input[j]!=','; j++){ //去除掉每一个
          num = num*10+ (int)(input[j] - '0');
        }
        i = j+1;
      }
      else{
        for(j=i; j<len && input[j]!=';'; j++){ //去除掉每一个
          num = num*10+ (int)(input[j] - '0');
        }
        i = j;
      }
      temp[level][pos] = num;
      pos++;
      if(j == len) break;
    }
  }
  //遍历检查是否合格;
}   

第二块:转化问题:
之所以初次编写,没写出来是因为当时没有绕过弯来,因为本次最短路径还有一条需要作为参考的就是额外的过路费,因为有的道路是需要交过路费而有的不需要。
所以过路费也作为一个维度来看,这时候为了简单的运用迪杰特斯拉算法就得到我们所需要的输出结果,其实就是把过路费给去掉,也就是在需要友过路费的路段,直接把过路费转化成路径长度即可。
//把过路费转化为路径长度就算是把两个维度降成一个维度来考虑了,至少目前为止是我想到的解决的办法;

   struct Graphic{
    int** value_;   
    int** store_; //存储判定是否需要加过路费;
    int  num_of_nodes_;     
  } 
  g.num_of_nodes_  = temp[count_of_array-1][1]-temp[0][0]+1;

  g.value_  = new int*[num_of_nodes_];
  g.store_  = new int*[num_of_nodes_];

  for(int i=0; i<num_of_nodes_; i++){
     g.value_[i] = new int[num_of_nodes_]; 
     g.store_[i] = new int[num_of_nodes_];
  }

  for(int i=0; i<count_of_array; i++){
     g.value_[temp[i][0]][temp[i][1]] = temp[i][2]; //权重;
     g.value_[temp[i][1]][temp[i][0]] = temp[i][2];  
     g.store_[temp[i][0]][temp[i][1]] = temp[i][3]; //道路类型;
     g.store_[temp[i][1]][temp[i][0]] = temp[i][3];               
  }
  //写的啰嗦了应该在上一步直接解决,有待改进;
  for(int i=0; i<g.num_of_nodes_; i++){
    for(int j=0; j<g.num_of_nodes_; j++){
      if(g.store_[i][j] == 100){
         //need to change; 
         g.value_[i][j]+= ((g.value_[i][j]*0.5*100)/52); 
      }       
    }     
  }

第三块: 传统的迪杰特斯拉算法: 思想:遇获得最短路径,(在迭代过程中使得每次所走的一定是距离远点最短的路径(局部最优解)), 结合全局的搜索获得全局最优解。这也是为什么这个方法是o(n)的原因,如果o(n)的话解出的一定是局部最优解

代码初版:

“`

include

include

include

using namespace std;
//找最短路径的问题;
const int INFINITY = 65535;
struct Graphic{
int** value_;
int** store_; //存储判定是否需要加过路费;
int num_of_nodes_;
}
void Process(string& input,int** temp);
void FindTheMinDis(int start,int* path,int* dis,Graphic& g);
int main(){

string input;
int** temp;
int* path;
int* dis;
int count_of_array = 0;
int start_pos = 0, end_pos = 0;
Graphic g;

getline(cin,input);
//处理输入问题;
for(int i=0; i

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值