BOJ 14306 Monster Path (Small)
sorohue가 PS하는 블로그
BOJ 14306 Monster Path (Small)
문제 링크입니다.
문제 요약
격자판마다 몬스터가 한 마리씩 있습니다. 상하좌우로 움직여 해당 칸에 방문할 때마다 그 몬스터 잡기를 시도할 수 있습니다. 몬스터를 잡을 확률은 그 칸에 몬스터 유인기가 있으면 $p$, 아니면 $q$입니다. 이미 몬스터를 잡은 칸에 다시 방문했다고 몬스터를 또 잡을 수는 없습니다.
최적의 방법으로 $S$번 이동했을 때 잡을 수 있는 몬스터의 수의 최대 기댓값을 구하세요.
다 해 보기
움직일 수 있는 방향은 상하좌우 4가지 뿐이고, $S$가 5 이하이므로 가능한 경로의 가짓수는 $2^{10} = 1024$ 이하입니다.
어떤 칸에 처음 방문했을 때 $r$의 확률로 몬스터를 잡을 수 있다고 합시다. 그뒤 그 칸에 다시 방문해 몬스터를 잡을 확률은, 저번 방문에서 몬스터를 잡지 못했어야 하므로 $(1-r)r$이 됩니다.
같은 논리로, 어떤 칸에 방문할 때마다 해당 칸에서 몬스터를 잡을 확률을 기댓값에 더한 뒤 해당 칸의 확률에 $(1-r)$을 곱하는 방식으로 진행하면 각 경로마다 ${\cal O}(S)$에 기댓값을 구할 수 있고, 마찬가지로 ${\cal O}(S)$에 각 칸에서 몬스터를 잡을 확률을 초기 상태로 롤백할 수 있습니다. 입력 제외 시간 복잡도는 테스트 케이스 당 ${\cal O}(S 2^S)$입니다.
Large도 같은 방법으로 해결할 수 있습니다. 경계를 벗어났다가 돌아오는 경로가 생기지 않도록 유의해 주세요.
코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using pll = pair<ll, ll>;
const int dy[]={-1,0,1,0},dx[]={0,1,0,-1};
char board[25][25];
ld d[25][25];
ld solve(){
int n, m, sy, sx, t; cin >> n >> m >> sy >> sx >> t; sy++; sx++;
ld p, q; cin >> p >> q;
for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++){
cin >> board[i][j];
if(board[i][j] == 'A') d[i][j] = p;
else d[i][j] = q;
}
ld ans = 0;
for(int path = 0; path < (1<<(2*t)); path++){
int y = sy, x = sx; ld tmp = 0; bool ok = 1;
for(int i = 0; i < t; i++){
int k = (path>>(i*2))&3;
y += dy[k]; x += dx[k];
if(y < 1 || y > n || x < 1 || x > m){
ok = 0; continue;
}
tmp += d[y][x];
if(board[y][x] == 'A') d[y][x] *= 1-p;
else d[y][x] *= 1-q;
}
if(ok) ans = max(ans, tmp);
y = sy; x = sx;
for(int i = 0; i < t; i++){
int k = (path>>(i*2))&3;
y += dy[k]; x += dx[k];
if(y < 1 || y > n || x < 1 || x > m) continue;
if(board[y][x] == 'A') d[y][x] = p;
else d[y][x] = q;
}
}
return ans;
}
int main(){
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
int T; cin >> T; cout << fixed << setprecision(12);
for(int tc = 1; tc <= T; tc++) cout << "Case #" << tc << ": " << solve() << '\n';
}
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.