POJ3635 Full Tank?(DP + Dijkstra)
2016-05-15 19:50
323 查看
题目大概说,一辆带有一个容量有限的油箱的车子在一张图上行驶,每行驶一单位长度消耗一单位油,图上的每个点都可以加油,不过都有各自的单位费用,问从起点驾驶到终点的最少花费是多少?
这题自然想到图上DP,通过最短路来转移方程:
dp[u][c]表示当前在u点油箱还有c单位油时的最少花费
不过,我T得好惨,因为在转移时我通过枚举在各个结点加多少油转移,这样对于每个状态都for一遍枚举,整个时间复杂度还得乘上转移的代价,即油箱最大容量。。。
事实上,状态dp[u][c]只需要向两个方向转移:
向dp[u][c+1]转移,即原地加一单位油
向dp[v][c-w(u,v)]((u,v)∈E 且 w(u,v)<=c),即走到下一个结点
另外用SPFA会TLE,用Dijkstra即可,1000×100的状态数稳定AC。
这题自然想到图上DP,通过最短路来转移方程:
dp[u][c]表示当前在u点油箱还有c单位油时的最少花费
不过,我T得好惨,因为在转移时我通过枚举在各个结点加多少油转移,这样对于每个状态都for一遍枚举,整个时间复杂度还得乘上转移的代价,即油箱最大容量。。。
事实上,状态dp[u][c]只需要向两个方向转移:
向dp[u][c+1]转移,即原地加一单位油
向dp[v][c-w(u,v)]((u,v)∈E 且 w(u,v)<=c),即走到下一个结点
另外用SPFA会TLE,用Dijkstra即可,1000×100的状态数稳定AC。
#include<cstdio> #include<cstring> #include<queue> #include<algorithm> using namespace std; #define INF (1<<30) #define MAXN 1111 #define MAXM 111111 struct Edge{ int v,w,next; }edge[MAXM<<1]; int NE,head[MAXN]; void addEdge(int u,int v,int w){ edge[NE].v=v; edge[NE].w=w; edge[NE].next=head[u]; head[u]=NE++; } int vs,vt,cap; int price[MAXN],d[MAXN][111]; bool vis[MAXN][111]; struct Node{ int u,w,d; Node(int _u=0,int _w=0,int _d=0):u(_u),w(_w),d(_d){} bool operator<(const Node &nd)const{ return nd.d<d; } }; int dijkstra(){ memset(d,127,sizeof(d)); memset(vis,0,sizeof(vis)); priority_queue<Node> que; for(int i=0; i<=cap; ++i){ d[vs][i]=price[vs]*i; que.push(Node(vs,i,d[vs][i])); } while(!que.empty()){ Node nd=que.top(); que.pop(); if(nd.u==vt) return nd.d; if(vis[nd.u][nd.w]) continue; vis[nd.u][nd.w]=1; if(nd.w<cap && d[nd.u][nd.w+1]>d[nd.u][nd.w]+price[nd.u]){ d[nd.u][nd.w+1]=d[nd.u][nd.w]+price[nd.u]; que.push(Node(nd.u,nd.w+1,d[nd.u][nd.w+1])); } for(int i=head[nd.u]; i!=-1; i=edge[i].next){ int v=edge[i].v; if(edge[i].w>nd.w) continue; int nw=nd.w-edge[i].w; if(d[v][nw]>d[nd.u][nd.w]){ d[v][nw]=d[nd.u][nd.w]; que.push(Node(v,nw,d[v][nw])); } } } return INF; } int main(){ int n,m,q,a,b,c; scanf("%d%d",&n,&m); for(int i=0; i<n; ++i){ scanf("%d",price+i); } memset(head,-1,sizeof(head)); while(m--){ scanf("%d%d%d",&a,&b,&c); addEdge(a,b,c); addEdge(b,a,c); } scanf("%d",&q); while(q--){ scanf("%d%d%d",&cap,&vs,&vt); int res=dijkstra(); if(res==INF) puts("impossible"); else printf("%d\n",res); } return 0; }
相关文章推荐
- 利用随机数随机生成指定位数的字符串
- nodejs及npm命令
- 计数排序
- 高精度除法(高精除以低精)——一步一步算法篇
- mongodb增删改查基本操作
- android开发人员获取sqlite
- 5月中旬的一些总结
- 常见排序算法(比较排序)及比较
- 【Scala】响应式编程思想
- 使用ASM字节码框架实现AOP功能
- Java的个人总结
- 第11周学习进度条
- 2016年团体程序设计天梯赛-模拟赛
- Java冒泡随笔
- HUST——1106xor的难题之二(异或树状数组单点修改和区间查询)
- React基础入门
- ubuntu sudo apt-get update 失败 解决方法
- python面向对象1
- oracle实例的内存(SGA和PGA)调整,优化之原理和方法
- 杂记