Full Tank?[POJ3635]

版权声明:作为一个蒟蒻,转载时请通知我这个蒟蒻 https://blog.csdn.net/zyszlb2003/article/details/89408328

题面描述

给定 N N 个加油站,其中有一个是秋名山。 M M 条无向边,每条边都有 x , y , d x,y,d d d x x 从这条边走到 y y 的距离,现在给你一辆车 A E 86 \large AE86 ,你需要驾驶这辆 A E 86 \large AE86 从家到秋名山去飙车!但是,秋名山和家的位置都是不固定的,而且你的 A E 86 \large AE86 的油箱也是不固定的,途中有些加油站,这些加油站的每个单位距离的油的价钱 p i p_i 不定,它们会变换,而且,你有时候不能到秋名山开车,因为路途有跤警 。先给定一个询问 Q Q ,每个询问 Q Q ,给出家 s t st 、秋名山 e d ed 、以及 A E 86 \large AE86 的油箱储量 c w cw ,求最小费用.
输入格式
第一行给出 N N , M M
接下来一行,分别为 p 0 , p 1 , p 2 , . . . . . . , p n 1 p_0,p_1,p_2,......,p_{n-1} .
3 3 ~ M + 2 M+2 行,分别为 x i , y i , d i x_i,y_i,d_i .
M + 3 M+3 行,给出 Q Q
接下来 Q Q 行,给出每一个 c w , s t , e d cw,st,ed
初始化的油箱储量为 0 0
输出格式
对于每一个 Q Q
若无解,输出“impossible”
否则,输出最小费用。
样例输入
5 5
10 10 20 12 13
0 1 9
0 2 8
1 2 1
1 3 11
2 3 7
2
10 0 3
20 1 4
样例输出
170
impossible

思路

既然这道题跑图,则 b f s bfs
这里状态可以有两种选择,我们可以

  1. 停在这个加油站加油,
  2. 去别的加油站加油。

既然我们不知道在这个加油站加多少油,那就每一次只加一个单位的油,避免状态的损失,上限就是 c w cw .
仔细思考发现,这样很容易超时,且多出许多无用状态。
那尝试考虑优先队列 p r i o r i t y q u e u e \operatorname{priority_{queue}}
我们就可以很清晰地得到状态:

  1. 停在这里加一个单位的油
  2. 到别的加油站去

由于我们是保证最小花费w的(优先队列的性质),所以可以得到最小解。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<deque>
using namespace std;
const int N=1e3+10;
const int M=1e4+10;
const int inf=0x3f3f3f3f;
struct edge{int x,y,next,d;}a[M<<1];int len,last[N];
void ins(int x,int y,int d){a[++len].x=x,a[len].y=y;a[len].d=d;a[len].next=last[x];last[x]=len;}
struct node
{
	int w,f,x;//w为花费,f为油量,x为位置。 
	node(){}
	node(int x,int f,int w):x(x),f(f),w(w){}
	bool operator <(const node a)const{return w>a.w;}
	//*this在<前面,a在<后面 ,交换时,*this.w若大于a.w,会把*this远离根,a靠近根,从而将大根堆变为小根堆。 
};
int p[N],c[N][110];bool v[N][110];
int main()
{
	int n,m,Q;scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++)scanf("%d",&p[i]);
	for(int i=1;i<=m;i++){int x,y,d;scanf("%d%d%d",&x,&y,&d);ins(x,y,d);ins(y,x,d);}
	scanf("%d",&Q);
	while(Q--)
	{
		int st,ed,cw;scanf("%d%d%d",&cw,&st,&ed);
		memset(v,false,sizeof(v));memset(c,0x3f,sizeof(c));
		c[st][0]=0;
		priority_queue<node>q;
		q.push(node(st,0,0));
		while(!q.empty())
		{
			node now=q.top();q.pop();
			int x=now.x,f=now.f,w=now.w;
			if(v[x][f])continue;
			if(x==ed)break;
			if(f<cw)
			{
				if(w+p[x]<c[x][f+1])
				{
					c[x][f+1]=w+p[x];
					q.push(node(x,f+1,c[x][f+1]));
				}
			}
			for(int k=last[x];k;k=a[k].next)
			{
				int y=a[k].y,d=a[k].d;
				if(d<=f&&c[y][f-d]>w)
				{
					c[y][f-d]=w;
					q.push(node(y,f-d,c[y][f-d]));
				}
			}
			v[x][f]=true;
		}
		if(c[ed][0]==inf)puts("impossible");
		else printf("%d\n",c[ed][0]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zyszlb2003/article/details/89408328