问题描述
试题编号: | 201712-4 |
试题名称: | 行车路线 |
时间限制: | 1.0s |
内存限制: | 256.0MB |
问题描述: | 问题描述 小明和小芳出去乡村玩,小明负责开车,小芳来导航。 输入格式 输入的第一行包含两个整数n, m,分别表示路口的数量和道路的数量。路口由1至n编号,小明需要开车从1号路口到n号路口。 输出格式 输出一个整数,表示最优路线下小明的疲劳度。 样例输入 6 7 样例输出 76 样例说明 从1走小道到2,再走小道到3,疲劳度为52=25;然后从3走大道经过4到达5,疲劳度为20+30=50;最后从5走小道到6,疲劳度为1。总共为76。 数据规模和约定 对于30%的评测用例,1 ≤ n ≤ 8,1 ≤ m ≤ 10; |
分析:迪杰斯特拉算法。
import java.util.*;
public class Main {
static Scanner sc = new Scanner(System.in);
static int n,m;//路口数,路段数
static long[][] g;//无向图的邻接矩阵,从下标为0开始记
static int[][] gt;//0大路,1小路
static int[] prior;//路口i在dis里的上一个路口
static long[] dis;//到节点i的最小疲劳度
static boolean[] s;//已确定的路口的集合
static long[] past;//0表示到达路口i走的是大路,否则走的是小路(值为小路的实际累加长度)
static int INF=Integer.MAX_VALUE;
static void initialize(){
n=sc.nextInt();//路口数
m=sc.nextInt();//路段数
g=new long[n][n];
gt=new int[n][n];
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
g[i][j]=Integer.MAX_VALUE;
for(int i=0;i<m;i++){
int type=sc.nextInt();
int start=sc.nextInt()-1;
int end=sc.nextInt()-1;
int cost=sc.nextInt();
gt[start][end]=type;
gt[end][start]=type;
g[start][end]=cost;
g[end][start]=cost;
}
}
static long newDis(int v,int w){//v为中间点,w为目标点。前提是存在v到w的路段
long d=0;
//不更新prior
if(gt[v][w]==0){//大路
d=dis[v]+g[v][w];
past[w]=0;
}
else{//小路
if(past[v]==0){//前面是大路
d=dis[v]+g[v][w]*g[v][w];
past[w]=g[v][w];
}
else{//前面是小路
d=dis[v]-past[v]*past[v]+(past[v]+g[v][w])*(past[v]+g[v][w]);
past[w]+=g[v][w];
}
}
return d;
}
static void dijkstra(){
s=new boolean[n];
dis=new long[n];
past=new long[n];
prior=new int[n];
for(int i=0;i<n;i++){
if(g[0][i]<INF){//存在路段0->i
if(gt[0][i]==0){//大路
dis[i]=g[0][i];
past[i]=0;
}
else{//小路
dis[i]=g[0][i]*g[0][i];
past[i]=g[0][i];
}
prior[i]=0;
}
else{//不存在路段0->i
dis[i]=INF;
past[i]=0;
prior[i]=-1;
}
}
s[0]=true;
dis[0]=0;
while(true){
int v=-1;
for(int i=0;i<n;i++){
if(!s[i]&&(v==-1||dis[i]<dis[v])){
v=i;
}
}
if(v==-1)
break;
s[v]=true;
for(int i=0;i<n;i++){
if(!s[i]&&g[v][i]<INF&&newDis(v,i)<dis[i]){
dis[i]=newDis(v,i);
prior[i]=v;
}
}
}
}
public static void main(String[] args) {
initialize();
dijkstra();
System.out.println(dis[n-1]);
}
}