解法
bitでいろいろやるのは自明っぽかったので察して、
Dijkstraじゃね?って思ったがMLEで詰んでいた。
動的計画法らしかったのでそうした。
bit[クリアしてるかの状態] = 最短時間
ソース
#include<iostream> #include<algorithm> using namespace std; #define INF ( 1 << 30 ) int N,mas[16][17],dp[1<<17]; int rec(int bit){ if(dp[bit]) return dp[bit]; if(!bit) return 0; int ret = INF; for(int i = 0 ; i < N ; i++ ){ if(!(bit & (1 << i))) continue; int min_cost = mas[i][0]; for(int j = 0 ; j < N ; j++ ){ if(i != j && !(bit & (1 << j))) min_cost = min( min_cost, mas[i][j+1]); } ret = min( ret, min_cost + rec(bit&~(1 << i))); } return dp[bit] = ret; } int main(){ while(cin >> N , N ){ fill_n( dp, 1<<17, 0); for(int i = 0 ; i < N ; i++ ){ for(int j = 0 ; j <= N ; j++ ){ cin >> mas[i][j]; } } cout << rec((1 << N)-1) << endl; } }ループ
#include<cstdio> #include<algorithm> using namespace std; #define INF ( 1 << 25 ) int N,mas[16][17],dp[1<<16]; int solve(){ for(int i = 0 ; i < 1 << N ; i++ ) dp[i] = INF; dp[(1 << N) - 1] = 0; for(int bit = (1 << N) - 1 ; bit >= 0 ; bit-- ){ for(int i = 0 ; i < N ; i++ ){ if(!(bit & (1 << i))) continue; int min_cost = mas[i][0]; for(int j = 0 ; j < N ; j++ ){ if(!(bit & (1 << j))) min_cost = min( min_cost, mas[i][j+1]); } dp[bit&~(1<<i)] = min(dp[bit&~(1<<i)],min_cost + dp[bit]); } } return dp[0]; } int main(){ while(scanf("%d",&N), N ){ for(int i = 0 ; i < N ; i++ ){ for(int j = 0 ; j <= N ; j++ ){ scanf("%d",&mas[i][j]); } } printf("%d\n",solve()); } }
最初浮かんだ解法,Dijjkstraは状態数が多すぎた。
used[16][1<<16] = used[今の場所][bit]。今の場所が不要なことを察したかった。
上のDPと似てるけど修正したやつ。
#include<iostream> #include<string> #include<algorithm> #include<vector> #include<queue> #include<map> using namespace std; #define fr first #define sc second #define INF ( 1 << 30 ) typedef pair < int , int > P; int N, cost[16][17]; bool used[1<<16]; int Dijkstra(){ priority_queue< P , vector<P> , greater<P> > que; for(int i = 0 ; i < N ; i++ ){ que.push(P(cost[i][0],((1<<N)-1)&~(1<<i))); } fill_n( used, 1<<16, false); while(!que.empty()){ P p = que.top(); que.pop(); if(p.sc == 0) return p.fr; if(used[p.sc]++) continue; for(int i = 0 ; i < N ; i++ ){ if(!((p.sc >> i) & 1)) continue; int ret = cost[i][0]; for(int j = 0 ; j < N ; j++ ){ if(i != j && !((p.sc >> j) & 1)) ret = min(ret, cost[i][j+1]); } que.push(P(p.fr+ret,p.sc&~(1 << i))); } } return -1; } int main(){ while(cin >> N , N){ for(int i = 0 ; i < N ; i++ ){ for(int j = 0 ; j <= N ; j++ ){ cin >> cost[i][j]; } } cout << Dijkstra() << endl; } }
0 件のコメント:
コメントを投稿