SRM 237 DIV1 Hard MirrorPlacement
問題
H*Wのマップが与えられる。
マップはそれぞれ '.': 空白, '#': 壁, '/': "/"の形の鏡, '`': "\"の形の鏡
マップの周囲は壁に囲われており、ちょうど2つだけ穴があいている。
一方の穴からもう一方の穴へ光を通したい。
光は壁に当たると吸収され、鏡に当たると直角に反射する。
鏡に裏表はなく、どちらからでも反射する。
鏡を空白のマスにいくつか置ける。
一方の穴からもう一方の穴へ光を通すとき、置く鏡の数を最小化せよ。
ただしどうやっても光を通せない場合は-1を返せ
解答
まず、鏡を置いたマスを2回以上通ることは最適ではない。
なぜなら、2回が直角の角度で来る場合は鏡の角度を変えればショートカットでき、水平の場合はループしてるか最初の穴に戻るだけだからである。
なので、単に鏡の置いた枚数を距離としたBFSをすれば良い
コメント
Example6のケースを考慮してなくて、Exampleに救われた。これは駄目だね。もしExampleになかったら!
その後も遅すぎて駄目だ。もしバグったりミスしたら、どうすればいいか一回"本当に"冷静に考えよう!
コード
#include <string> #include <vector> #include <queue> #include <cstring> #define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i)) #define reu(i,l,u) for(int (i)=(int)(l);(i)<(int)(u);++(i)) #define pb(x) push_back(x) #define mp(x,y) make_pair((x),(y)) #define mset(m,v) memset(m,v,sizeof(m)) #define INF 0x3f3f3f3f using namespace std; typedef pair<int,int> pii; typedef vector<pair<int,int> > vpii; struct MirrorPlacement { int mirrors(vector <string> a) { int h = a.size(), w = a[0].size(); vpii holes; reu(i, 1, h-1) { if(a[i][0]=='.') holes.pb(mp(i, 0)); if(a[i][w-1]=='.') holes.pb(mp(i, w-1)); } reu(j, 1, w-1) { if(a[0][j]=='.') holes.pb(mp(0, j)); if(a[h-1][j]=='.') holes.pb(mp(h-1, j)); } static const int dy[4] = {0,1,0,-1}, dx[4] = {1,0,-1,0}; deque<pair<int,pair<pii,int> > > q; { pii p = holes[0]; int d = p.second==0 ? 0 : p.second==w-1 ? 2 : p.first==0 ? 1 : 3; q.pb(mp(0, mp(p, d))); } static int dist[4][55][55]; mset(dist, INF); while(!q.empty()) { pair<pii,int> st = q.back().second; int ww = q.back().first, d = st.second, y = st.first.first, x = st.first.second; q.pop_back(); if(dist[d][y+1][x+1] <= ww) continue; dist[d][y+1][x+1] = ww; #define BOUND(y,x) (0<=(y)&&(y)<h&&0<=(x)&&(x)<w) #define OK(y,x) (BOUND(y,x)&&a[y][x]!='#') if(st.first == holes[1] && !BOUND(y+dy[d], x+dx[d])) return ww; if(!BOUND(y+dy[d], x+dx[d])) continue; static const int mirror1[4] = {3,2,1,0}, mirror2[4] = {1,0,3,2}; int nd = d; if(a[y][x] == '/') nd = mirror1[d]; else if(a[y][x] == '`') nd = mirror2[d]; if(OK(y + dy[nd], x + dx[nd])) q.push_back(mp(ww, mp(mp(y + dy[nd], x + dx[nd]), nd))); if(a[y][x] == '.') rep(mirror, 2) { nd = (mirror==0 ? mirror1 : mirror2)[d]; q.push_front(mp(ww + 1, mp(mp(y, x), nd))); } } return -1; } };