AOJ : 0224 - Bicycle Diet
アルゴリズム
ダイクストラ法によって解ける.
真っ先に思い浮かぶのは,
bool closed[現在いるノード][辿ったケーキ屋を表すビット]
によって解く方法ですが, 今回は負のエッジが存在するため, この単純なダイクストラでは通りません.
改善法は,
int closed[現在いるノード][辿ったケーキ屋を表すビット]
として, 今までの最小コストを記憶しておき, 最小コスト以上になってしまうときは, 探索打ち切りとしてしまう方法.
(shimeji_tanさんの解法を参考にしました : http://d.hatena.ne.jp/simezi_tan/20101019/1287462266)
プログラム
import java.util.*; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); int INF = Integer.MAX_VALUE; while(true){ int m = sc.nextInt(); int n = sc.nextInt(); int k = sc.nextInt(); int d = sc.nextInt(); if(m == 0) break; int[] cake = new int[m]; for(int i=0;i<m;i++) cake[i] = sc.nextInt(); //[0]:スタート //[1]~[m]:ケーキ屋 //[m+1]~[m+n]:ランドマーク //[m+n+1]:市役所 int[][] map = new int[m+n+2][m+n+2]; for(int[] tmp : map) Arrays.fill(tmp,INF); for(int i=0;i<d;i++){ String a = sc.next(); String b = sc.next(); int cost = sc.nextInt(); int from=-1,to=-1; if(a.equals("H")) from = 0; else if(a.equals("D")) from = m+n+1; else if(a.charAt(0) == 'C') from = Integer.parseInt(a.substring(1)); else from = m + Integer.parseInt(a.substring(1)); if(b.equals("H")) to = 0; else if(b.equals("D")) to = m+n+1; else if(b.charAt(0) == 'C') to = Integer.parseInt(b.substring(1)); else to = m + Integer.parseInt(b.substring(1)); map[from][to] = map[to][from] = k * cost; } PriorityQueue<State> open = new PriorityQueue<State>(); int[][] closed = new int[m+n+4][1000]; for(int[] tmp : closed) Arrays.fill(tmp,INF); int ans = INF; open.add(new State(0,0,0)); while(!open.isEmpty()){ State st = open.poll(); if(closed[st.id][st.used] <= st.cost) continue; closed[st.id][st.used] = st.cost; if(st.id == m+n+1){ ans = Math.min(ans,st.cost); } for(int i=0;i<m+n+2;i++){ if(map[st.id][i] != INF && ( i<1 || m<i || (st.used & (1<<i)) == 0 ) ){ int ncost = st.cost + map[st.id][i]; int nused = st.used; if(1 <= i && i <= m){ ncost -= cake[i-1]; nused |= (1<<i); } if(closed[i][nused] > ncost) open.add(new State(ncost,i,nused)); } } } System.out.println(ans); } } } class State implements Comparable<State>{ int cost,id,used; State(int cost,int id,int used){ this.cost = cost; this.id = id; this.used = used; } public int compareTo(State st){ return this.cost - st.cost; } }