poj 3635 最短路搜索

题目:小车的容量有限,在各个城市加油的费用不同,通过城市之间的路要耗油,用最小的费用实现从给定源点到目标

基本方法:

把每个城市到达以后的状态拆分成C + 1个点,采用优先队列存储状态

状态表示为:

到达城市 u

剩余油量 d

最小花费 v

以最小花费为优先级排序,逐步搜索每一个状态,那么找到目标点的时候,即是到达目标点的最小花费

类似于bfs和dij的方法

#include <iostream>
#include <vector>
#include <map>
#include <list>
#include <set>
#include <deque>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <iomanip>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <string>
#include <sstream>
#include <cstring>
#include <queue>
using namespace std;

///宏定义
const int  INF = 1000000000;
const int MAXN = 1200;
const int maxn = MAXN;
///全局变量 和 函数
#define CL(a,num) memset(a,num,sizeof(a));

struct node
{
	int v;
	int len;
	int next;
}p[MAXN * 10 * 2];

struct qnode
{
	int d;      //剩余油量
	int u;      //到达城市
	int cost;   //花费
	qnode(int x,int y,int z): u(x), d(y), cost(z){}
	friend bool operator < (qnode a,qnode b)
	{
		return  a.cost > b.cost ;
	}
};
int num, a[maxn], nextt[maxn], dp[maxn][102], n, m, vis[maxn][102];
void add(int u, int v, int len)
{
	p[num].v = v;
	p[num].len = len;
	p[num].next = nextt[u];
	nextt[u] = num++;
}
priority_queue<qnode> que;
int bfs(int s, int e, int c)
{
	int i, j;
	while (!que.empty())
		que.pop();

	for (i = 0; i <= n; ++i)
	{
		for (j = 0; j <= c; ++j)
		{
			dp[i][j] = INF; //dp[i][j]表示到达城市i剩余油量为j的最小花费
		}
	}

	CL(vis, 0);
	dp[s][0] = 0;
	que.push(qnode(s, 0, 0));
	while (!que.empty())
	{
		qnode  b = que.top();
		que.pop();
		int u = b.u;
		int cost = b.cost;
		int d = b.d;
		vis[u][d] = 1;//从u 到 d  花费 最小的标记
		if (u == e)
			return cost;
		//加一升油,满足松弛条件该状态进入队列
		if (d + 1 <= c && !vis[u][d + 1] && dp[u][d + 1] > dp[u][d] + a[u])
		{
			dp[u][d + 1] = dp[u][d] + a[u] ;
			que.push(qnode(u, d+1, dp[u][d+1]));
		}
		for (i = nextt[u]; i != -1; i = p[i].next)
		{
			int v = p[i].v;
			int len = p[i].len;
			//如果到达V结点 所需要的消费的油量比当前可提供的油量到V的多,进入队列
			if(d >= len &&!vis[v][d - len] && dp[v][d - len] > cost)
			{
				dp[v][d - len] = cost;
				que.push(qnode(v, d - len, cost));
			}
		}
	}
	 return -1 ;

}
int main()
{
	///变量定义
	int i, j;
	int s, e, c, x, y, d, q;
	while (scanf("%d%d", &n, &m) != EOF)
	{
		for (i = 0; i < n; ++i)
		{
			scanf("%d", &a[i]);
		}

		CL(nextt, -1);
		num = 0;
		for (i = 0; i < m; ++i)
		{
			scanf("%d%d%d", &x, &y, &d);
			add(x, y, d);
			add(y, x, d);
		}
		scanf("%d", &q);
		while (q--)
		{
			scanf("%d%d%d", &c, &s, &e);
			int ans = bfs(s, e, c);
			if (ans != -1)
				printf("%d\n", ans);
			else
				printf("impossible\n");
		}
	}

	///结束
	return 0;
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值