9、【3】行车路线 (选做)(图)
[问题描述]
小明和小芳出去乡村玩,小明负责开车,小芳来导航。
小芳将可能的道路分为大道和小道。大道比较好走,每走1公里小明会增加1的疲劳度。小道不好走,如果连续走小道,小明的疲劳值会快速增加,连续走s公里小明会增加s2的疲劳度。
例如:有5个路口,1号路口到2号路口为小道,2号路口到3号路口为小道,3号路口到4号路口为大道,4号路口到5号路口为小道,相邻路口之间的距离都是2公里。如果小明从1号路口到5号路口,则总疲劳值为(2+2)2+2+22=16+2+4=22。
现在小芳拿到了地图,请帮助她规划一个开车的路线,使得按这个路线开车小明的疲劳度最小。
[基本要求]
输入格式:
输入的第一行包含两个整数n, m,分别表示路口的数量和道路的数量。路口由1至n编号,小明需要开车从1号路口到n号路口。
接下来m行描述道路,每行包含四个整数t, a, b, c,表示一条类型为t,连接a与b两个路口,长度为c公里的双向道路。其中t为0表示大道,t为1表示小道。保证1号路口和n号路口是连通的。
输出格式
输出一个整数,表示最优路线下小明的疲劳度。
样例输入
6 7
1 1 2 3
1 2 3 2
0 1 3 30
0 3 4 20
0 4 5 30
1 3 5 6
1 5 6 1
样例输出
76
样例说明
从1走小道到2,再走小道到3,疲劳度为52=25;然后从3走大道经过4到达5,疲劳度为20+30=50;最后从5走小道到6,疲劳度为1。总共为76。
课程设计要求:
(1)要求从文本文件中输入;
(2)采用适当的数据结构存储由输入数据中的道路所形成的图结构;
(3)编写尽可能优的算法,处理好连续走小道造成的疲劳值的指数增长(提示:基于迪杰斯特拉算法进行改进即可完成本题);
(4)除严格按题目要求进行输出以外,还要求输出最优路线的路径,以及从出发点到各个点的最小疲劳值。
#include<iostream>
#include<stdio.h>
#include<windows.h>
#include<fstream>
#include<map>
#include<set>
#include<queue>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<math.h>
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#define OK 1
#define TRUE 1
#define FALSE 0
#define MAXSIZE 1024
#define INFINIT 0x3f3f3f3f
using namespace std;
typedef struct Type{
int kind; //0big,1small
int from; //
int to; //
int distance; //
}*TYPE,Type;
typedef struct Tire{
int tire = 0; //start
int road = 1; //start
};
int Sqare(int x){
return x*x;
}
int Min(int x,int y){
return x<y?x:y;
}
int n,m;
int dl[MAXSIZE][MAXSIZE],xl[MAXSIZE][MAXSIZE];
int Dis1[MAXSIZE],Dis2[MAXSIZE];
int flag[MAXSIZE];
int sum_1 = 0; //走小道总路程
int Tired(Type ty,Tire ti,int FinalRoad){
if(ty.from != ti.road){ //非出发点
// exit(0);
// return 0;
ti.tire +=0; //不走这条路劳累不变
}
else{
if(ty.kind == 0){
ti.tire = Sqare(sum_1); //由小道变大道,结算sum_1
ti.tire = ti.tire + ty.distance; //大道结算
ti.road = ty.to; //所在路口改变
sum_1 = 0; //重置
}
if(ty.kind ==1){
sum_1 = sum_1 + ty.distance;
}
while(ti.road == FinalRoad) {
return ti.tire;
}
}
}
void Qiu(TYPE T[],Tire Ti){
for(int i = 0; i < sizeof(T);i++){
}
}
void Cmp(){
for(int k = 1; k <= n ; k++){
for(int i = 1; i <= n ; i++){
for(int j = 1; j <= n ; j++){
if(xl[i][j] > xl[i][k]+xl[k][j] && i != k && i != j && j != k){
xl[i][j]=xl[j][i]=xl[i][k]+xl[k][j];
}
}
}
}
}
void Spfa(){
memset(Dis1,INFINIT,sizeof(Dis1));
memset(Dis2,INFINIT,sizeof(Dis2));
queue<int> q;
Dis1[1]=Dis2[1]=0;
q.push(1);
flag[1]=1;
while(!q.empty()){
int u=q.front();
q.pop();
flag[u]=0;
for(int i=1;i<=n;i++){ //Dis1,Dis2:当前第i段路是大路
int w=dl[u][i];
if(Dis1[i]>Dis1[u]+w){ //走大路
Dis1[i]=Dis1[u]+w;
if(!flag[i]){
q.push(i);
flag[i]=1;
}
}
if(Dis1[i]>Dis2[u]+w){ //走大路
Dis1[i]=Dis2[u]+w;
if(!flag[i]){
q.push(i);
flag[i]=1;
}
}
if( xl[u][i]<INFINIT ){ //小路能到达
w=xl[u][i]*xl[u][i];
if(Dis2[i]>Dis1[u]+w){ //走小路 ,前驱为小路时不能走小路
Dis2[i]=Dis1[u]+w;
if(!flag[i])
{
q.push(i);
flag[i]=1;
}
}
}
}
}
}
int main()
{
memset(xl,INFINIT,sizeof(xl));
memset(dl,INFINIT,sizeof(dl));
int t,a,b,c;
cin>>n>>m;
Type T[m];
for(int i=1;i<=m;i++){
cin>>t>>a>>b>>c;
T[i].kind = t; //Have no time to use
T[i].from = a;
T[i].to = b;
T[i].distance = c;
if(t == 1 && xl[a][b] > c)
xl[a][b]=xl[b][a]=c;
else if(t == 0 && dl[a][b] > c)
dl[a][b]=dl[b][a]=c;
}
Cmp();
Spfa();
cout<<min(Dis1[n],Dis2[n]);
return 0;
}