AOJ : 1048 - Provident Housewife
問題概要
http://rose.u-aizu.ac.jp/onlinejudge/ProblemSet/description.jsp?id=1048&lang=jp
日本語の問題文なので説明は省略
アルゴリズム
次の状態で遷移させて, ダイクストラ法で解きました.
- 今いるスーパーの番号
- すでに購入した商品 (ビット管理)
- 購入金額合計 (比較優先1)
- 歩いた距離 (比較優先2)
ちなみにJavaで解くと, 2秒かかってTLEだったので, いちいちC++で書き直して, 無理やり通しましたw
他の人は, ダイクストラではない方法で解いてるみたいです.
みなさん, 僕よりかなり実行速度が速いので, 他の人の解法も検索してみるといいと思います.
プログラム
class P{ public: int id,bought,price,walk; P(int _id,int _bought,int _price,int _walk){代入処理省略} bool operator<(const P &p)const{ if(price == p.price) return walk > p.walk; return price > p.price; } }; int t[12][12],market[12][16]; bool closed[12][33000]; vector<string> name[12]; vector<int> price[12]; int main(void){ int n; while(cin>>n,n){ rep(i,n){ int k; cin>>k; name[i] = vector<string>(k); price[i] = vector<int>(k); rep(j,k) cin>>name[i][j]>>price[i][j]; } int q; cin>>q; string list[q]; rep(i,q) cin>>list[i]; memset(t,0,sizeof(t)); int m; cin>>m; rep(i,m){ int a,b,cost; cin>>a>>b>>cost; t[a][b] = t[b][a] = cost; } memset(market,-1,sizeof(market)); rep(i,n){ rep(j,name[i].size()){ rep(k,q){ if(list[k] == name[i][j]){ market[i][k] = price[i][j]; } } } } priority_queue<P> open; memset(closed,0,sizeof(closed)); open.push(P(0,0,0,0)); P ans(0,0,0,0); while(!open.empty()){ P p = open.top(); open.pop(); if(closed[p.id][p.bought]) continue; closed[p.id][p.bought] = true; if(p.id == 0 && p.bought == (1<<q)-1){ ans = p; break; } for(int i=0;i<=n;i++){ if(t[p.id][i] > 0){ open.push(P(i,p.bought,p.price,p.walk+t[p.id][i])); } } if(p.id > 0){ int idx = p.id - 1; for(int i=0;i<q;i++){ if(market[idx][i] > 0){ open.push(P(p.id,p.bought|(1<<i),p.price+market[idx][i],p.walk)); } } } } if(ans.bought == 0) cout<<"impossible\n"; else cout<<ans.price<<" "<<ans.walk<<endl; } return 0; }