Problem 2254 Fastest Route ICPC模擬国内予選2011 C
解き方
頂点数が16以下なので、ビットDPで解ける。
int s;で (0000...0000)2の各ビットを頂点に対応させ訪れたかどうかの情報を保持させる。
s == 1 == (0000...0001)2なら、1つ目の頂点を訪れて他は訪れていない。
s == 2 == (0000...0010)2なら、2つ目
s == 3 == (0000...0011)2なら、1つ目と2つ目
頂点数を仮に5とすると全て訪れている状態は
s == (0000...011111)2 = 31 == (1<<5)-1
ソースコード
#include <iostream> #include <algorithm> using namespace std; typedef long long int ll; #define FOREACH(t,p,it) for(t::iterator it=p.begin();it!=p.end();++it) #define foreach(t,p) FOREACH(t,p) #define all(p) p.begin(),p.end() #define REP(i,n) for(ll i=0;i<n;i++) #define rep(p) REP(i,p) const ll INF = 10000000LL; const int MX = 16; int times[MX][MX+1]; int dp[1<<MX]; int n; int solve(int s) { if( dp[s] ) return dp[s]; if( s == (1<<n)-1 ) return dp[s]=0; ll sum = INF, cache; REP(i,n) { if(s>>i&1) continue; sum=min(sum,(cache=solve(s|1<<i))+times[i][0]); REP(t,n) { if(!(s>>t&1)) continue; sum=min(sum,cache+times[i][t+1]); }} return dp[s]=sum; } int main() { while(cin>>n&&n) { REP(i,1<<n) dp[i]=0; REP(i,n) REP(t,n+1) cin>>times[i][t]; cout << solve(0) << endl; } return 0; }