题意:给出n个地点 和 每个地点的油价 ,有 m 条边 , 并给出每条边长度 。1单位汽油可以走1千米 , 油箱的容量为 c , 在初始点 s 时 , 油箱中的油为 0 , 求s 到 t 的最小花费 。
解法: 定义 状态 d[i][j] 表示到达 地点 i 且油箱中有 j 单位油时的最小 花费。 对于状态的转移时 , 有两种方法:
1、把每个点的所有状态都求出
2、不把每个点的状态都求出 , 而是一单位一单位的加油。
对于第一种方法 , 会超时 , 因为每个点的状态太多 , 但是能用的状态就那么几个 , 因此得用第二种方法 , 进行状态的转移。
确定状态转移之后 , 我就可以用 dijkstra + 堆进行优化。
代码:
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <queue>
#include <vector>
using namespace std;
#define maxn 1010
#define INF 0xfffffff
struct node
{
int u , fle , d;
bool operator < (const node& chs) const
{
return d > chs.d;
}
};
struct edge
{
int u , d;
int next;
}grap[20010];
int n , m;
int ci[maxn] , pre[maxn][110];
int head[maxn];
int d[maxn][110];
int s , t , c;
void init()
{
memset(head , -1 , sizeof(head));
}
void add_edge(int x , int y , int z , int &k)
{
grap[k].u = y;
grap[k].d = z;
grap[k].next = head[x];
head[x] = k++;
grap[k].u = x;
grap[k].d = z;
grap[k].next = head[y];
head[y] = k++;
}
int dijkstra()
{
priority_queue<node>q;
memset(pre , 0 , sizeof(pre));
int i ;
memset(d , -1 , sizeof(d));
d[s][0] = 0;
node f , e;
e.u = s;
e.fle = e.d = 0;
q.push(e);
while(!q.empty())
{
e = q.top(); q.pop();
if(e.u == t) return e.d;
for(i = head[e.u]; i != -1 ; i = grap[i].next)
{
if(e.fle >= grap[i].d)
{
int fuel=e.fle-grap[i].d;
if(d[grap[i].u][fuel]==-1||d[grap[i].u][fuel]>e.d)
{
f.u = grap[i].u;
f.fle = fuel;
f.d = e.d;
d[grap[i].u][fuel] = e.d;
// printf("tt.u %d cost %d fuel %d\n",tt.u,tt.fuel,tt.cost);
q.push(f);
}
}
if(e.fle < c)
{
if(d[e.u][e.fle+1]==-1||d[e.u][e.fle+1]>e.d+ci[e.u])
{
f.u = e.u;
f.fle = e.fle+1;
f.d = e.d+ci[e.u];
d[e.u][f.fle] = e.d+ci[e.u];
// printf("tt.u %d cost %d fuel %d\n",tt.u,tt.fuel,tt.cost);
q.push(f);
}
}
}
}
return -1;
}
int main()
{
while(scanf("%d %d" , &n , &m) != EOF)
{
init();
int i , x , y , z;
int k = 0;
for(i = 0; i < n; i++)
scanf("%d" , &ci[i]);
for(i = 0; i < m; i++)
{
scanf("%d %d %d" , &x , &y , &z);
add_edge(x , y , z , k);
}
int p;
scanf("%d" , &p);
for(i = 1; i <= p; i++)
{
scanf("%d %d %d" , &c , &s , &t);
x = dijkstra();
if(x == -1) cout<<"impossible"<<endl;
else
printf("%d\n" , x);
}
}
return 0;
}