結果
問題 | No.134 走れ!サブロー君 |
ユーザー |
![]() |
提出日時 | 2015-08-15 01:37:26 |
言語 | C++11 (gcc 13.3.0) |
結果 |
AC
|
実行時間 | 12 ms / 5,000 ms |
コード長 | 2,969 bytes |
コンパイル時間 | 1,334 ms |
コンパイル使用メモリ | 172,556 KB |
実行使用メモリ | 6,016 KB |
最終ジャッジ日時 | 2024-10-14 17:14:55 |
合計ジャッジ時間 | 1,880 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 15 |
ソースコード
#include <bits/stdc++.h>typedef long long ll;typedef unsigned long long ull;#define FOR(i,a,b) for(int (i)=(a);i<(b);i++)#define REP(i,n) FOR(i,0,n)#define RANGE(vec) (vec).begin(),(vec).end()using namespace std;class GoSabrou {public:void solve(void) {// 巡回セールスマン問題の応用int x0,y0;cin>>x0>>y0;int N;cin>>N;// 配達先vector<tuple<int,int,double>> dest;// 出発地も登録しておくdest.emplace_back(x0,y0,0);REP(i,N){int x,y;double w;cin>>x>>y>>w;dest.emplace_back(x,y,w);}++N; // 出発点分加算// 距離を事前計算しておくconst int inf = (1<<30);vector<vector<int>> dist(N,vector<int>(N,inf));REP(i,N)FOR(j,i+1,N){const auto &p = dest[i];const auto &q = dest[j];// 距離はマンハッタン距離int d = abs(get<0>(p)-get<0>(q)) + abs(get<1>(p)-get<1>(q));dist[i][j] = dist[j][i] = d;}// 総荷重量を計算しておく// weights[unvis] := 未配達先が unvis であるときの総重量vector<double> weights(1<<N, 0);REP(unvis, (1<<N)){double w = 0;REP(i,N) if ( unvis & (1<<i) )w += get<2>(dest[i]);weights[unvis] = w;}// dp[unvis][i] := 未配達先が unvis で現在地が v のときの配達終了までの最短時間vector<vector<double>> dp(1<<N, vector<double>(N,inf));// O((1<<N)*N^2)// 頂点 0 からスタートして全部巡回させるdp[(1<<N)-1][0] = 0;// 0 頂点を除いた全ビットからスタートfor (int unvis = (1<<N)-2; unvis >= 0; --unvis){// 次の移動先 v 毎REP(v,N){// 移動前 u 毎REP(u,N){// 移動前が未到達なら飛ばすif ( unvis & (1<<u) )continue;double cost = (weights[unvis]+100.0)/120.0 * dist[u][v] + get<2>(dest[v]);dp[unvis][v] = min(dp[unvis][v], dp[unvis|(1<<u)][u] + cost);}}}// 一周してもどってきたcout<<setprecision(20)<<dp[0][0]<<endl;}};#if 1int main(int argc, char *argv[]){ios::sync_with_stdio(false);auto obj = new GoSabrou();obj->solve();delete obj;return 0;}#endif