POJ3635 周游诸城:变形的SPFA/Dijkstra最短路+动规思想+Heap
2013-07-30 20:24
337 查看
POJ3635 周游诸城:变形的SPFA/Dijkstra最短路+动规思想+Heap
分类: Algorithm2013-07-1317:26 126人阅读 评论(0) 收藏 举报
本来就有点小感冒,不过看到就快出国了,还是陪下爸妈,去海边玩了下,结果连续的长途开车奔波,加上海边游泳,消耗了不少体力,终于今天回来彻底病倒,喉咙痛到说不出话。打算这两天就把之前玩的一些题目给总结了吧,接下来得开始弄各种手续和那边导师安排的工作了。
POJ3635,很有一道意思的题目,最后做出来后,你会发现它既有SPFA和Dijkstra的朴素思想,又有动态规划的巧妙,但是又不能生搬硬套这些算法。
我一开始想到的是用动规,推导出:
costArr[i][j] = min{ ( e(i,i') + (j - k) ) * price[i'] + costArr[i‘][k] }
其中costArr[i][j]为起点s到达某点i时,还剩下单位油量j的最小代价;e(i,i')表示相邻的两个点i,i'的边长;price[i]表示点i的单位汽油价格。该公式意思是枚举和点i相邻的各个状态:costArr[i'][k],从而找出最优的选择。
得到该公式后,算法的流程就和Dijkstra几乎一样了,稍微不一样是这里把costArr[i'][k]当做一个状态。然后算法的每次迭代就从最小堆中拿出最小的costArr[i'][k],更新和它相邻的状态点costArr[i][j]。这样子一共有n*c个状态点。
然后我根据该公式写成的代码,测试了好些数据,都ok,结果一提交,居然time exceeds limitation。无奈之下去再参考下别人的思路,发现该题时间要求比较严格,原来还要剪枝。如何剪枝?核心是“每个状态点,只加1单位油,或者不加油直接走到相邻状态点”,这样子也可以把所有的n*c个状态点给遍历。
至于算法复杂度,窃以为,用最小堆实现,参考Dijkstra的算法复杂度分析,上面的原始算法和剪枝优化的复杂度都是为O( (nc+ec)*log(nc) ),只是剪枝优化后有点深度搜索的味道,尽可能的往纵深去搜索,实际应用中,往往只需要遍历更小的状态数就可以到达终点。这个分析,如有不对万望各位兄台指正。
[java] view
plaincopy
import java.util.*;
class Node
{
public Node()
{
nodeId = -1;
price = 0;
links = new ArrayList<Link>();
}
public Node(int id, int p)
{
nodeId = id;
price = p;
links = new ArrayList<Link>();
}
public int nodeId;
public int price;
public ArrayList<Link> links;
}
class Link
{
public Link()
{
lnodeId = -1;
distance = 0;
}
public Link(int nId, int dis)
{
lnodeId = nId;
distance = dis;
}
public int lnodeId;
public int distance;
}
class StateNode
{
public StateNode()
{
}
public StateNode(int nId, int cap, int cost)
{
this.nodeId = nId;
this.cap = cap;
this.cost = cost;
}
public int nodeId;
public int cap;
public int cost;
}
class Comp implements Comparator<StateNode>
{
@Override
public int compare(StateNode arg0, StateNode arg1) {
return arg0.cost - arg1.cost;
}
}
public class Main {
public static int costArr[][] = new int[1001][101];
public static boolean visFlag[][] = new boolean[1001][101];
public static int MAX = 1<<30;
//关键的算法函数。
public static int DijSearch(ArrayList<Node>graph, int s, int e, int c)
{
int minCost = -1;
int n = graph.size();
for(int i=0;i<n;i++)
{
Arrays.fill(costArr[i], MAX);
Arrays.fill(visFlag[i], false);
}
//Initialize the start node.
costArr[s][0] = 0;
PriorityQueue<StateNode> queue = new PriorityQueue<StateNode>(n*(c+1),new Comp());
queue.add(new StateNode(s,0,0));
while(queue.isEmpty() == false)
{
StateNode hn = queue.poll();
if(hn.nodeId == e && hn.cap == 0)
{
minCost = hn.cost;
break;
}
if(visFlag[hn.nodeId][hn.cap] == true)
{
continue;
}
else
{
visFlag[hn.nodeId][hn.cap] = true;
}
//Plus one.
if(hn.cap + 1 <= c && costArr[hn.nodeId][hn.cap+1] > costArr[hn.nodeId][hn.cap] + graph.get(hn.nodeId).price)
{
costArr[hn.nodeId][hn.cap+1] = costArr[hn.nodeId][hn.cap] + graph.get(hn.nodeId).price;
queue.add(new StateNode(hn.nodeId,hn.cap+1,costArr[hn.nodeId][hn.cap+1]));
}
ArrayList<Link> links = graph.get(hn.nodeId).links;
for(int i=0;i<links.size();i++)
{
int lnId = links.get(i).lnodeId;
int linkDis = links.get(i).distance;
if(linkDis > c || linkDis > hn.cap)
continue;
// Go over costArr[ links[i].nodeId ][j]
if ((visFlag[lnId][hn.cap - linkDis] == false)) {
if ( (hn.cost < costArr[lnId][hn.cap - linkDis]) ) {
costArr[lnId][hn.cap - linkDis] = hn.cost;
queue.add(new StateNode(lnId, hn.cap - linkDis, hn.cost));
}
}
}
}
return minCost;
}
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
int n,m;
n = scan.nextInt();
m = scan.nextInt();
//Initialize the graph
ArrayList<Node> graph = new ArrayList<Node>(n);
//The nodes
for(int i=0;i<n;i++)
{
int pri = scan.nextInt();
graph.add(new Node(i,pri));
}
//The edges
for(int i=0;i<m;i++)
{
int u,v,d;
u = scan.nextInt();
v = scan.nextInt();
d = scan.nextInt();
graph.get(u).links.add(new Link(v,d));
graph.get(v).links.add(new Link(u,d));
}
//The query
int q,s,e,c;
q = scan.nextInt();
for(int i=0;i<q;i++)
{
c = scan.nextInt();
s = scan.nextInt();
e = scan.nextInt();
int dis = DijSearch(graph, s, e, c);
if(dis == -1)
System.out.println("impossible");
else
System.out.println(dis);
}
}
}
相关文章推荐
- POJ3635 周游诸城:变形的SPFA/Dijkstra最短路+动规思想+Heap
- POJ 2263 Heavy Cargo (SPFA+Dijkstra,最短路变形)
- POJ 2263 Heavy Cargo (SPFA+Dijkstra,最短路变形)
- POJ - 1797 Heavy Transportation(最短路变形,SPFA,Dijkstra)
- poj 1797 最短路变形dijkstra
- HDOJ 2680 Choose the best route (最短路变形 Dijkstra && SPFA)
- POJ 2253 Frogger 最短路-Dijkstra的变形形式
- POJ 1797 Heavy Transportation&&POJ 2253 Frogger 最短路 dijkstra变形
- poj 3635 BFS 最短路变形
- POJ 2387 Til the Cows Come Home(最短路 Dijkstra/spfa)
- POJ 2253 - 最短路变形 SPFA+Dijstra
- poj 1847 Tram 【最短路 dijkstra + floyd + spfa】
- poj 3463 dijkstra变形(求最短路和次短路的数量)
- POJ 1797 Heavy Transportation&&POJ 2253 Frogger 最短路 dijkstra变形
- Poj 2253 Frogger (最短路变形 dijkstra)
- poj 2240 Arbitrage 最短路变形 spfa
- POJ---2449 Remmarguts' Date[K短路入门题(Dijkstra()||Spfa()+A*)]
- 【最短路入门专题1】E - Heavy Transportation Poj 1797【Dijkstra变形题】
- 最短路练习10/poj/1511 Invitation Cards ,(两次spfa),(单源最短路,优先队列优化的Dijkstra)
- poj 1062 dijkstra求最短路变形