题目链接:POJ 3635
题目大意:
给定一张图,若干点之间的路径、距离和每个点的油价。并已知每条路的耗油量,给一些询问,求每个询问中从起点到终点用指定油箱容量的车所得到的最小耗费。
思路:
BFS+优先队列。无向图可以用邻接表来储存。
实现:
邻接表:邻接表使用vector实现相对于用二维数组实现不需要记录各个点的邻接点个数,只需要通过push_back加入到vector中,在调用时通过size就可以知道邻接点个数。
struct graph{
int des;//路径连接点
int dist;//距离
};
vector<graph> vect[MAXN];
void add(int a,int b,int c)//无向图,a、b分别为两点,c为距离
{
graph tem;
tem.des=b;
tem.dist=c;
vect[a].push_back(tem);
tem.des=a;
tem.dist=c;
vect[b].push_back(tem);
}
优先队列:使用stl中的priority_queue实现。
struct Node{
int pos,oil,sp;
//pos储存当前点,oil储存车在当前点时的油量,sp储存在当前点时的花费。
bool operator < (const Node & a) const
{
return sp>a.sp;
}
};
BFS:定义标记数组vis[i][j]表示在当前点i时车的油量有j。
int bfs()
{
priority_queue<Node> que;
Node now,next;
now.pos=s;
now.oil=0;
now.sp=0;
sp[s][0]=0;
que.push(now);
while(!que.empty())//每次选择队首进行扩展,一种扩展为在当前点加油,一种扩展为前往邻接点。
{
now=que.top();
que.pop();
if(now.pos==e)
return now.sp;
vis[now.pos][now.oil]=1;//标记
if(now.oil+1<=cap&&!vis[now.pos][now.oil+1])//在当前点加油,每次加一升直到加满。
{
sp[now.pos][now.oil+1]=sp[now.pos][now.oil]+price[now.pos];
next.pos=now.pos;
next.oil=now.oil+1;
next.sp=now.sp+price[now.pos];
que.push(next);
}
for(int i=0;i<(int)vect[now.pos].size();i++)//前往邻接点,通过for循环遍历当前点的所有邻接点
{
int des=vect[now.pos][i].des;
int tem=now.oil-vect[now.pos][i].dist;
if(tem>=0&&!vis[des][tem]&&now.sp<sp[des][tem])//判断当前油量是否可以到达邻接点
{
sp[des][tem]=now.sp;
next.pos=des;
next.oil=tem;
next.sp=now.sp;
que.push(next);
}
}
}
return -1;
}
完整代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <limits>
#include <vector>
using namespace std;
const int MAXN=1e3+5;
const int MAXO=1e2+5;
const int MAX=INT_MAX;
struct graph{
int des;
int dist;
};
struct Node{
int pos,oil,sp;
bool operator < (const Node & a) const
{
return sp>a.sp;
}
};
int n,m,u,v,d,q,cap,s,e;//变量具体含义同题中所述。
int price[MAXN],vis[MAXN][MAXO],sp[MAXN][MAXO];
//price[i]储存点[i]的油价,sp[i][j]储存在点i的耗油量j
vector<graph> vect[MAXN];
void add(int a,int b,int c)//建立邻接表
{
graph tem;
tem.des=b;
tem.dist=c;
vect[a].push_back(tem);
tem.des=a;
tem.dist=c;
vect[b].push_back(tem);
}
int bfs()
{
priority_queue<Node> que;
Node now,next;
now.pos=s;
now.oil=0;
now.sp=0;
sp[s][0]=0;
que.push(now);
while(!que.empty())
{
now=que.top();
que.pop();
if(now.pos==e)
return now.sp;
vis[now.pos][now.oil]=1;
if(now.oil+1<=cap&&!vis[now.pos][now.oil+1])//当前点加油
{
sp[now.pos][now.oil+1]=sp[now.pos][now.oil]+price[now.pos];
next.pos=now.pos;
next.oil=now.oil+1;
next.sp=now.sp+price[now.pos];
que.push(next);
}
for(int i=0;i<(int)vect[now.pos].size();i++)//前往邻接点
{
int des=vect[now.pos][i].des;
int tem=now.oil-vect[now.pos][i].dist;
if(tem>=0&&!vis[des][tem]&&now.sp<sp[des][tem])
{
sp[des][tem]=now.sp;
next.pos=des;
next.oil=tem;
next.sp=now.sp;
que.push(next);
}
}
}
return -1;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
scanf("%d",&price[i]);
while(m--)
{
scanf("%d%d%d",&u,&v,&d);
add(u,v,d);
}
scanf("%d",&q);
while(q--)
{
scanf("%d%d%d",&cap,&s,&e);
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++)
for(int j=0;j<MAXO;j++)
sp[i][j]=MAX;
int ans=bfs();
if(ans<0)
printf("impossible\n");
else
printf("%d\n",ans);
}
return 0;
}