題目描述
有一盜墓者潛入一金字塔盜寶。當她(難道是Lara Croft ?)打開一個寶箱的時候,突然冒出一陣煙(潘多拉的盒子?),她迅速意識到形勢不妙,三十六計走爲上計……由於她盜得了金字塔的地圖,所以她希望能找出最佳逃跑路線。地圖上標有N個室,她現在就在1室,金字塔的出口在N室。她知道一個祕密:那陣煙會讓她在直接連接某兩個室之間的通道內的行走速度減半。她希望找出一條逃跑路線,使得在最壞的情況下所用的時間最少。
輸入格式
輸入文件的第一行有兩個正整數N(3≤N≤100)和M(3≤M≤2000);下面有M行,每行有三個數正整數U、V、W,表示直接從U室跑到V室(V室跑到U室)需要W(3≤W≤255)秒。
輸出格式
輸出所求的最少時間(單位爲秒)。
輸入輸出樣例
輸入 #1
7 8
1 2 10
2 3 12
3 4 20
4 7 8
1 7 34
2 5 10
5 6 12
6 4 13
輸出 #1
66
說明/提示
樣例解釋 Sample Explan:
基本上有三種路線:
(1)1 -> 2 -> 3 -> 4 -> 7
總時間爲:10+12+20+8=50,最壞的情況是“3->4”那一段,要多花20秒(因爲行走速度減半),所以這條路選最壞需要70秒;
(2)1 -> 2 -> 5 -> 6 -> 4 -> 7
總時間爲:10+10+12+13+8=53,最壞的情況是“6->4”那一段,要多花13秒,所以這條路選最壞需要66秒;
(3)1 -> 7
總時間爲:34=34,最壞的情況是“1->7”那一段,要多花34秒,所以這條路選最壞需要68秒。
解法:A*
- 首先考慮A*算法,如何構造估價函數,因爲估價函數要小於等於實際,一條路徑都會有一個翻倍的路,所以我們可以把估價函數設爲這個點到終點的最短路,加上前面搜索的最大值,因爲最大值已經在最短路里麪包含,所以我們只需要再加一次就相當於加了兩次
- 每次在優先隊列中取出估值函數最小的那個點開始拓展,如果當前的點是終點,那我們直接輸出步數加上前面的最大值即可
- 我設了x爲當前值,g爲估值函數,maxx爲前面的最大值,step是當前的距離
AC代碼
#include<cstdio>
#include<cstring>
#include<queue>
#define re register int
using namespace std;
struct edge {
int nex,to,w;
}e[4005];
struct node {
int x,g,maxx,step;
bool operator < (node A) const {
return A.g<g;//按估值排序
}
};
int n,m,cnt,head[105],d[105];
bool v[105]; queue<int> q;
inline int read() {
int x=0,cf=1;
char ch=getchar();
while(ch<'0'||ch>'9') {
if(ch=='-') cf=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') {
x=(x<<3)+(x<<1)+(ch^48);
ch=getchar();
}
return x*cf;
}
inline void add(int x,int y,int z) {
e[++cnt].to=y,e[cnt].w=z,e[cnt].nex=head[x],head[x]=cnt;
}
inline void spfa() {
memset(d,0x3f,sizeof(d));
memset(v,false,sizeof(v));
q.push(n),d[n]=0,v[n]=1;
while(q.size()) {
int x=q.front(); q.pop(); v[x]=0;
for(re i=head[x];i;i=e[i].nex) {
int y=e[i].to,z=e[i].w;
if(d[y]>d[x]+z) {
d[y]=d[x]+z;
if(!v[y]) q.push(y),v[y]=1;
}
}
}
}
inline void Astar() {
priority_queue<node> q; node tmp; tmp.step=0;
tmp.g=d[1],tmp.maxx=0,tmp.x=1; q.push(tmp);
while(q.size()) {
node now=q.top(); q.pop();
if(now.x==n) {
printf("%d",now.maxx+now.step);
return;
}
for(re i=head[now.x];i;i=e[i].nex) {
node temp; temp.step=now.step+e[i].w;
temp.maxx=max(now.maxx,e[i].w);
temp.g=temp.step+temp.maxx+d[e[i].to];
temp.x=e[i].to; q.push(temp);
}
}
}
int main() {
n=read(),m=read();
for(re i=1;i<=m;i++) {
int x=read(),y=read(),z=read();
add(x,y,z),add(y,x,z);
}
spfa(); Astar();
return 0;
}