题目:小车的容量有限,在各个城市加油的费用不同,通过城市之间的路要耗油,用最小的费用实现从给定源点到目标
基本方法:
把每个城市到达以后的状态拆分成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;
}