Problem 0146 : Lupin The 4th

Problem 0146 : Lupin The 4th
http://rose.u-aizu.ac.jp/onlinejudge/ProblemSet/description.jsp?id=0146

  • 問題概要

あちこち回って荷物を回収するが、荷物をもてばもつほど、うごきが遅くなる。

  • 解法

DP. ビットで荷物の状態を表しループを回す。
dp[今どこか][ビットでどの荷物を拾ったか];

  • ソース
#include<iostream>
#include<algorithm>
#include<vector>

#define INF 1e+100
#define vint vector<int>

using namespace std;

main(){
  int n; 
  cin >> n;

  int MAX = (1<<n), ID[n], d[n], box[n];
  
  for(int i=0; i<n; i++){
    cin >> ID[i] >> d[i] >> box[i];
  }

  double dp[n][MAX];
  vint path[n][MAX];

  int w[MAX];

  for(int i=0; i<MAX; i++){
    int sum=0, cnt=0;
    for(int j=1; j<MAX; j=(j<<1), cnt++){
      if((i&j) != 0){
	sum += box[cnt];
      }
    }
    w[i] = sum * 20;
  }

  fill(&dp[0][0], &dp[n-1][MAX], INF);
  
  for(int i=0; i<n; i++){
    dp[i][1<<i] = 0;
    path[i][1<<i].push_back(i);
  }


  for(int i=0; i<MAX; i++){
    double v = 2000.0/(double)(70 + w[i]);
    for(int j=0; j<n; j++){
      int now = (1 << j);
      if( (i&now) == 0)continue;
      for(int k=0; k<n; k++){
	int next = (1 << k);
	if( (i&next) > 0)continue;
	double cost = (double)(abs(d[j] - d[k]))/v;
	if(dp[k][i|next] > dp[j][i] + cost){
	  dp[k][i|next] = dp[j][i] + cost;
	  path[k][i|next] = path[j][i];
	  path[k][i|next].push_back(k);
	}
      }
    }
  }

  double min = INF;
  vint ans;
  
  for(int i=0; i<n; i++){
    if(min > dp[i][MAX-1]){
      min = dp[i][MAX-1];
      ans = path[i][MAX-1];
    }
  }   
  for(int i=0; i<ans.size(); i++){
    if(i != 0){
      cout << ' ';
    }
    cout << ID[ans[i]];
  }
  cout << endl;
}

楽しかった。DPは楽しい。