AOJ 2302 - On or Off
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2302
概要
R x C の部屋と壁からなるマップが与えられる. M 個の (r[i], c[i]) にある部屋を与えられた順に巡る. スタート地点は (r[0], c[0]),ゴール地点は (r[M-1], c[M-1]).
部屋に入るときは必ずその部屋の電気をつけなければならない. ゴール地点についたときには全ての部屋の電気が消えていなければならない.
各部屋の電気には
- 付けるときのコスト
- 消すときのコスト
- つけっぱなしにしたときの,1ステップ毎のコスト
が設定されている.
コストが最小になるように電気を操作したとき,そのときのコストを出力する.
制約
- 0 < R <= 50
- 0 < C <= 50
- 2 <= M <= 1000
- ある部屋からある部屋までのパスは一意
- コストに関する制約が書かれていないが,int で通ったのでまぁそういうことだと思う
解法
通る部屋の時刻は一意に決まるので,シミュレーションにより通る時刻を記録し,2回以上通る部屋について,つけっぱなしの方が良いか,消してから付ける方が良いかを計算する.
aoj/2302.cc1 #include <iostream> 2 #include <vector> 3 #include <queue> 4 using namespace std; 5 6 int counter = 0; 7 8 void bfs(vector<vector<vector<int> > >& stamps, const vector<string>& grid, const pair<int,int>& start, const pair<int,int>& goal) 9 { 10 const int R = grid.size(), C = grid[0].size(); 11 queue<pair<int,int> > q; 12 q.push(start); 13 vector<vector<int> > prev(R, vector<int>(C, -1)); 14 while (!q.empty()) { 15 if (q.front() == goal) { 16 break; 17 } 18 const int i = q.front().first; 19 const int j = q.front().second; 20 q.pop(); 21 22 for (int d = 0; d < 4; d++) { 23 static const int di[] = {1, -1, 0, 0}; 24 static const int dj[] = {0, 0, 1, -1}; 25 const int k = i + di[d], l = j + dj[d]; 26 if (0 <= k && k < R && 0 <= l && l < C && grid[k][l] == '.' && prev[k][l] == -1) { 27 prev[k][l] = i*C + j; 28 q.push(make_pair(k, l)); 29 } 30 } 31 } 32 vector<pair<int,int> > path; 33 for (pair<int,int> pos = goal; pos != start;) { 34 path.push_back(pos); 35 const int p = prev[pos.first][pos.second]; 36 pos.first = p/C; 37 pos.second = p%C; 38 } 39 for (vector<pair<int,int> >::reverse_iterator it = path.rbegin(); it != path.rend(); ++it) { 40 stamps[it->first][it->second].push_back(counter++); 41 } 42 } 43 44 int main() 45 { 46 int R, C, M; 47 cin >> R >> C >> M; 48 vector<string> grid(R); 49 for (int i = 0; i < R; i++) { 50 cin >> grid[i]; 51 } 52 static int keep_costs[50][50], on_costs[50][50], off_costs[50][50]; 53 for (int i = 0; i < R; i++) { 54 for (int j = 0; j < C; j++) { 55 cin >> keep_costs[i][j]; 56 } 57 } 58 for (int i = 0; i < R; i++) { 59 for (int j = 0; j < C; j++) { 60 cin >> on_costs[i][j]; 61 } 62 } 63 for (int i = 0; i < R; i++) { 64 for (int j = 0; j < C; j++) { 65 cin >> off_costs[i][j]; 66 } 67 } 68 static pair<int,int> rooms[1000]; 69 for (int i = 0; i < M; i++) { 70 cin >> rooms[i].first >> rooms[i].second; 71 } 72 73 vector<vector<vector<int> > > stamps(R, vector<vector<int> >(C)); 74 stamps[rooms[0].first][rooms[0].second].push_back(counter++); 75 for (int i = 0; i < M-1; i++) { 76 bfs(stamps, grid, rooms[i], rooms[i+1]); 77 } 78 int ans = 0; 79 for (int i = 0; i < R; i++) { 80 for (int j = 0; j < C; j++) { 81 const vector<int>& s = stamps[i][j]; 82 if (!s.empty()) { 83 const int keep = keep_costs[i][j]; 84 const int on = on_costs[i][j]; 85 const int off = off_costs[i][j]; 86 ans += on; 87 for (vector<int>::const_iterator it = s.begin(); it+1 != s.end(); ++it) { 88 ans += min(off + on, keep*(*(it+1) - *it)); 89 } 90 ans += off; 91 } 92 } 93 } 94 cout << ans << endl; 95 return 0; 96 }