TopCoder SRM 573 Div1 Medium SkiResorts
問題
n個の場所が、向きのないゲレンデによってつながっている。
つながっている箇所はroad[i][j], road[j][i]がYになっている。
それぞれの場所には高さがあり、i番目の高さ≧j番目の高さのとき、
iからjに移動することができる。
今、0番目の場所からn-1番目の場所に移動したい。
移動できるように、それぞれの場所の高さを変更することができる。
高さの変更には、元々の高さをx、変更後の高さをyとすると|x-y|のコストがかかる。
何箇所でも高さを自由に変更できるとき、
かかるコストの最小値を求めよ。
制約条件
n≦50
高さは10^9以下
方針
変更後の高さは、他の場所の高さ以外にする必要はない。
なので、dp[pos][height]を、posの場所を高さheightにしているときの最短コストとして、
これを更新していけばよい。
これはグラフの最短路問題である。
ループがあるかなとか思ったので、SPFAを使ってみた。
ダイクストラだと、グラフを適当にやりすぎるとTLEする場合があったらしくよかった。
ソースコード
const ll inf = 1ll << 50; int n; vector<vi> e; ll h[50]; ll dp[50][50]; bool in[50][50]; class SkiResorts { public: long long minCost(vector <string> road, vector <int> altitude) { n = road.size(); e.clear(); e.resize(n); rep(i, n) rep(j, n) if(road[i][j] == 'Y') e[i].pb(j); rep(i, n) h[i] = altitude[i]; rep(i, n) rep(j, n) dp[i][j] = inf; rep(i, n) dp[0][i] = abs(h[0] - h[i]); queue<int> q; rep(i, n){ q.push(i); in[0][i] = 1; } while(!q.empty()){ int c = q.front() / 50, he = q.front() % 50; q.pop(); in[c][he] = 0; rep(i, e[c].size()) rep(j, n) if(h[he] >= h[j]){ int to = e[c][i]; ll nxt = dp[c][he] + abs(h[j] - h[to]); if(nxt < dp[to][j]){ dp[to][j] = nxt; if(!in[to][j]){ q.push(to * 50 + j); in[to][j] = 1; } } } } ll ans = inf; rep(i, n) ans = min(ans, dp[n - 1][i]); return ans >= inf ? -1 : ans; } };