洛谷P2349 金字塔 A* 搜索

題目描述

有一盜墓者潛入一金字塔盜寶。當她(難道是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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章