UVA 11367 - Full Tank? dijkstra+DP

传送门:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2352

题目大意:

n个城市有m条道路。每个城市的油价不一样,给出起点s和终点t,以及汽车的油箱的容量,求从城市s到城市 t 的最便宜路径。(一开始油箱是空的,你每次可以选择加多少升。假设每单位的距离消耗1L汽油)

思路:

dijkstra的变形。

用优先队列来维护当前花费的最小值。设dp[i][j]为到达城市i的消耗剩余汽油为j升的最小花费。

那么,经过每一站时候,如果到下一站加油可能最优,那么就加。(详见代码)

PS:

其实这个dp算状态转移吧,嗯,也算。不过我怎么觉得更像剪枝- -|||一开始没有TLE了

还有就是路是双向的。。WA了后发现。改了RE了。好吧数组太小。改了就AC了

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN=1000+10;  
const int MAXM=30000+10;  
const int INF=100000+10;  
int head[MAXN],len,dis[MAXN],cost[MAXN],n,m;  
int dp[MAXN][111];       //设dp[i][j]为到达城市i的消耗剩余汽油为j升的最小花费
struct edge  
{  
	int to,val,next;  
}e[MAXM];  

void add(int from,int to,int val)  
{  
	e[len].to=to;  
	e[len].val=val;  
	e[len].next=head[from];  
	head[from]=len++;  
}  
struct state
{
	int id,cost,move;
	state(int tid,int tcanmove,int tcurcost){id=tid;cost=tcurcost;move=tcanmove;}
	bool operator <(const state & x)const { 
		return cost > x.cost; 
	}
};
void dijkstra(int contain,int from,int to)
{
	memset(dis,0,sizeof(dis));
	for(int i=0;i<n;i++)
		for(int j=0;j<101;j++)
			dp[i][j]=INF;

	priority_queue<state> q;
	q.push(state(from,0,0));
	while(!q.empty())
	{
		state cur=q.top();
		if(cur.id==to)
		{
			printf("%d\n",cur.cost);
			return;
		}
		q.pop();
		if(cur.move<contain &&  dp[cur.id][cur.move+1] > cost[cur.id]+cur.cost) //满了不加,加了比之前的状态花费多不加
		{
			dp[cur.id][cur.move+1] = cost[cur.id]+cur.cost;
			q.push(state(cur.id,cur.move+1,cost[cur.id]+cur.cost));
		}
		for(int i=head[cur.id];i!=-1;i=e[i].next)
		{
			int id=e[i].to;
			if(cur.move < e[i].val) continue;//不够到下一站		
			if(dp[e[i].to][cur.move-e[i].val] > cur.cost)  // 到下一站的花费比记录的少就走起~
			{
				dp[e[i].to][cur.move-e[i].val] = cur.cost;
				q.push(state(e[i].to,cur.move-e[i].val,cur.cost));
			}
		}
	}
	printf("impossible\n");
}

int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		memset(head,-1,sizeof(head));
		len=0;

		for(int i=0;i<n;i++)
			scanf("%d",&cost[i]);
		for(int i=0;i<m;i++)
		{
			int from,to,val;
			scanf("%d%d%d",&from,&to,&val);
			add(from,to,val);
			add(to,from,val);
		}
		int q;
		scanf("%d",&q);
		while(q--)
		{
			int c,s,e;
			scanf("%d%d%d",&c,&s,&e);
			dijkstra(c,s,e);
		}
	}
	return 0;
}




你可能感兴趣的:(编程,dp,ACM,dijkstra,uva)