http://poj.org/problem?id=3635
给一张图,n个点,m条无向边,每个点都有自己的油价,每条路都需要消耗相应体积的油。q次询问,问一个小车,给定起点终点以及油箱容量,问到达终点的最小花费。
懵了!
看了下题解,是dp加bfs或者是dij
dp[i][j]是指到达i点剩j体积的油量的最小花费。
因为油最多只有100,所以可以这么做。
对于每一个状态,我们可以有2个选择,1 在这个点加1体积的油去更新相应状态 2 从这个点直接向能够达到的点出发去更新相应的状态。
同时我们要用有限队列来将花费排序,这样第一次找到终点就一定是最小花费。
同时我们要记录哪些状态我们已经更新到了。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cmath>
#include<cstring>
using namespace std;
struct edge{
int v,nex,cost;
};
struct pos{
int cost,fuel,u;
bool operator < (const pos a)const{
return cost>a.cost;
}
};
edge eg[22222];
priority_queue<pos> p;
int dp[1111][111];
int w[1111];
bool vis[1111][111];
int hea[1111];
int n,m;
int e;
void insert(int st,int ed,int cost)
{
eg[e].v=ed;
eg[e].cost=cost;
eg[e].nex=hea[st];
hea[st]=e++;
}
void bfs(int ca,int st,int ed)
{
pos t,tt;
t.u=st;
t.fuel=0;
t.cost=0;
vis[st][0]=1;
p.push(t);
dp[st][0]=0;
while(!p.empty())
{
tt=p.top();
p.pop();
vis[tt.u][tt.fuel]=1;
if(tt.u==ed)
{
cout<<tt.cost<<endl;
return ;
}
if(tt.fuel+1<=ca&&dp[tt.u][tt.fuel+1]>dp[tt.u][tt.fuel]+w[tt.u]&&vis[tt.u][tt.fuel+1]==0)
{
dp[tt.u][tt.fuel+1]=dp[tt.u][tt.fuel]+w[tt.u];
t.fuel=tt.fuel+1;
t.u=tt.u;
t.cost=dp[tt.u][tt.fuel+1];
p.push(t);
}
for(int i=hea[tt.u];i!=-1;i=eg[i].nex)
{
if(tt.fuel>=eg[i].cost&&vis[eg[i].v][tt.fuel-eg[i].cost]==0&&dp[eg[i].v][tt.fuel-eg[i].cost]>tt.cost)
{
dp[eg[i].v][tt.fuel-eg[i].cost]=tt.cost;
t.fuel=tt.fuel-eg[i].cost;
t.u=eg[i].v;
t.cost=tt.cost;
p.push(t);
}
}
}
cout<<"impossible"<<endl;
}
int main(){
while(cin>>n>>m)
{
e=0;
memset(hea,-1,sizeof(hea));
for(int i=0;i<n;i++)
cin>>w[i];
int u,v,cost;
for(int i=0;i<m;i++)
{
cin>>u>>v>>cost;
insert(u,v,cost);
insert(v,u,cost);
}
int q;
cin>>q;
int st,ed,ca;
while(q--)
{
cin>>ca>>st>>ed;
memset(vis,0,sizeof(vis));
memset(dp,0x3f3f3f3f,sizeof(dp));
while(!p.empty()){
p.pop();
}
bfs(ca,st,ed);
}
}
return 0;
}