PAT Advanced Level 1018. Public Bike Management (30)(Java and C++)
PAT Advanced Level 1018. Public Bike Management (30)
最短路徑問題。題意有三:1.時間最短 2.送出車輛最少 3.回收車輛最少 ps:(注意我的lessThan函式)
我的思路:是 SPFA(求出最短路徑) + DFS(獲取到Destination的所有最短路徑並存入pathVector)+遍歷path(求出各path min_send 和 min_back)
最終獲取send最下的path輸出(當有多個send相同的path,取back最小的)。
======================================================================================
大神的陷阱總結:
大神A:
這個題目自我感覺說的不太明確, 知道演算法可能還要注意一下兩點才能AC:
(1) 從PBMC到問題站點, 只能在這個順序上進行每個站點車輛數量的調整, 在從問題站點返回PBMC的時候不能調整路徑上的站點, 所以這個就導致有可能從PBMC送出去車輛也有可能帶回來車輛(直覺上好像不太合理, 既然要帶回來, 那麼從出去的時候幹嘛不少送一點呢?但是沒辦法, 這個題目似乎就是這麼要求的)
(2) 從哪些最短路徑總選擇調整的車輛的數量最小的那條時, 題目總的描述非常模糊以及容易誤導, 題目中是這麼說的:“If there are more than one shortest path, the one that requires the least number of bikes sent from PBMC will be chosen.”, 我一開始理解成了只要比較送出去的車輛的數量就行了, 其實測試資料才不是這麼測試的呢, 其實應該按照“首先選擇send最少的,send相同時選擇take back最少的。
大神B:
陷阱:調整路徑上站點的車輛數目時,不能把後面站點多出來的車輛返補回前面車輛數不夠的站點。乍看之下這是符合邏輯的,因為在前面的站點的時候不能知道後面的站點是什麼情況,所以按理應該逐個調整合理,後面的站點影響不到前面的調整。但是細想之後發現這其實是很死板的做法,現實當中設計這樣一個管理系統肯定能夠實時收集每個站點的自行車數,所以在出發前應該就能得出這條路徑上總的自行車數目,繼而就能得到最優的送出數。但四十是介樣子素通不過滴。
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.Vector;
public class Main {
static Main instance =new Main();
static int[] sBikes;
static int[] dis;
static final int Inf =Integer.MAX_VALUE-10000;
static Vector<Edge>[] map;
static boolean[] vis;
static int Cmax;
static int N;
static int Sp;
static int M;
public static void main(String[] args){
Scanner sc =new Scanner(System.in);
Cmax =sc.nextInt();
N =sc.nextInt();
Sp =sc.nextInt();
M =sc.nextInt();
sBikes =new int[N+1];
dis =new int[N+1];
map =new Vector[N+1];
vis =new boolean[N+1];
for(int i=0;i<=N;i++){
if(i==0){
sBikes[i]=Inf;
}
else{
sBikes[i]=sc.nextInt();
}
map[i] =new Vector<Edge>();
dis[i] =Inf;
vis[i] =false;
}
for(int i=0;i<M;i++){
int s1 = sc.nextInt();
int s2 = sc.nextInt();
int len = sc.nextInt();
Edge e1 =instance.new Edge();
e1.to=s2;
e1.len=len;
map[s1].add(e1);
Edge e2 =instance.new Edge();
e2.to =s1;
e2.len=len;
map[s2].add(e2);
}
spfa(0);
DFS(0,Sp,0);
Path path;
int extra;
for(int i=0;i<pathVector.size();i++){
path=pathVector.get(i);
Vector<Integer> stations =path.stations;
extra =0;
for(int j=0;j<stations.size();j++){
if(sBikes[stations.get(j)] <Cmax/2){
if(extra>0){
if(extra > Cmax/2-sBikes[stations.get(j)]){
extra -= Cmax/2-sBikes[stations.get(j)];
}
else{
path.send += Cmax/2-sBikes[stations.get(j)]-extra;
extra = 0;
}
}
else{
path.send += Cmax/2-sBikes[stations.get(j)];
}
}
else if(sBikes[stations.get(j)] >Cmax/2){
extra += sBikes[stations.get(j)] -Cmax/2;
}
}
path.back=extra;
}
path =pathVector.get(0);
for(int i=0;i<pathVector.size();i++){
if(lessThan(pathVector.get(i),path)){
path = pathVector.get(i);
}
}
System.out.print(path.send+" 0");
for(int i=0;i<path.stations.size();i++){
System.out.print("->"+path.stations.get(i));
}
System.out.print(" "+path.back);
}
public static boolean lessThan(Path p1,Path p2){
if(p1.send < p2.send)
return true;
if(p1.send == p2.send && p1.back < p2.back)
return true;
else
return false;
}
public static void spfa(int start){
dis[start]=0;
Queue<Integer> q =new LinkedList<Integer>();
q.add(start);
vis[start]=true;
while(!q.isEmpty()){
int cur =q.poll();
vis[cur]=false;
Vector<Edge> adjEdges =map[cur];
for(int i=0;i<adjEdges.size();i++){
int to =adjEdges.get(i).to;
int len=adjEdges.get(i).len;
if(dis[cur]+len <dis[to]){
dis[to] =dis[cur]+len;
if(!vis[to]){
q.add(to);
vis[to]=true;
}
}
}
}
}
static Vector<Integer> onePath = new Vector<Integer>();
static Vector<Path> pathVector = new Vector<Path> ();
public static void DFS(int st,int des,int distance){
if(st==des){
if(distance==dis[des]){
Vector<Integer> one_Path = new Vector<Integer>();
for(int i=0;i<onePath.size();i++){
one_Path.add(onePath.get(i));
}
Path path =instance.new Path();
path.stations=one_Path;
pathVector.add(path);
}
onePath.clear();
return ;
}
if(distance>dis[des]){
onePath.clear();
return;
}
Vector<Edge> adjEdges =map[st];
for(int i=0; i<adjEdges.size();i++){
int to =adjEdges.get(i).to;
int len=adjEdges.get(i).len;
if(dis[st]+len <= dis[to]){
onePath.add(to);
DFS(to,des,dis[st]+len);
}
}
onePath.clear();
}
class Path{
Vector<Integer> stations;
int send=0;
int back=0;
}
class Edge{
int to;
int len;
}
}
C++程式碼:參考部落格
使用DFS的程式碼:
http://blog.csdn.net/huntinggo/article/details/18941253
使用Dijkstra + DFS的程式碼:
http://www.cnblogs.com/luojiahu/p/3892608.html