시뮬레이션 문제다.


사람의 이동 경로가 주어지고 배터리 충전기의 개수와 위치, 강도, 범위가 주어질 때


이동 경로중에 충전 가능한 최대 배터리 양을 구하는 문제다.


배터리 충전기 개수가 8개밖에 안된다. 다음과 같은 방식으로 풀었다.



1. map[][]에 BC 번호에 따라 범위를 비트마스크로 표시한다. (굳이 비트마스크를 쓰지 않아도 된다.)

2. 사람을 옮긴다.

3. 각자의 map을 보고 만약 동일한 충전기의 범위 내라면 그걸 감안해서 계산하고 아니면 각자가 얻을 수 있는 최대값만을 구해서 더한다.




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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <iostream>
#include <algorithm>
using namespace std;
 
typedef long long ll;
typedef pair<intint> pii;
 
int a[101], b[101];
int map[11][11];
int dx[] = { 0,-1,0,1,0 }, dy[] = { 0,0,1,0,-1 };
int dxx[4][16= {
    { -1,0,1,0 },
-2,-1,0,1,2,1,0,-1 },
-3,-2,-1,0,1,2,3,2,1,0,-1,-2 },
-4,-3,-2,-1,0,1,2,3,4,3,2,1,0,-1,-2,-3 }
};
int dyy[4][16= {
    { 0,1,0,-1 },
0,1,2,1,0,-1,-2,-1 },
0,1,2,3,2,1,0,-1,-2,-3,-2,-1 },
0,1,2,3,4,3,2,1,0,-1,-2,-3,-4,-3,-2,-1 }
};
pii d[256][256];
pii bc[256];
 
 
 
int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    int t, n, m;
    int ans, i, j, k, x, y, c, p;
    cin >> t;
    for (int tc = 1; tc <= t; ++tc) {
        ans = 0;
        cin >> n >> m;
        for (i = 1; i <= n; ++i) cin >> a[i];
        for (i = 1; i <= n; ++i) cin >> b[i];
        for (i = 1; i < 11++i) for (j = 1; j < 11++j) map[i][j] = 0;
        for (i = 0; i < m; ++i) {
            cin >> y >> x >> c >> p;
            bc[1 << i] = { tc,p };
            if (x >= 1 && y >= 1 && x < 11 && y < 11) map[x][y] |= (1 << i);
            for (j = 0; j < c; ++j) for (k = 0; k < ((j + 1<< 2); ++k) {
                if (x + dxx[j][k] >= 1 && x + dxx[j][k] < 11 && y + dyy[j][k] >= 1 && y + dyy[j][k] < 11)
                    map[x + dxx[j][k]][y + dyy[j][k]] |= (1 << i);
            }
        }
        int ax = 1, ay = 1, bx = 10, by = 10, jj = 0, kk = 0, mv[2];
        for (i = 0; i <= n; ++i) {
            ax += dx[a[i]]; ay += dy[a[i]];
            bx += dx[b[i]]; by += dy[b[i]];
            j = map[ax][ay];
            k = map[bx][by];
            if (d[j][k].first != tc) {
                mv[0= 0;
                // 둘의 위치를 모두 포함하는 충전기가 하나라도 있다면
                if (j&k) {
                    for (; j; j -= jj) {
                        // a가 jj번째를 고르고
                        jj = j & -j;
                        for (k = map[bx][by]; k; k -= kk) {
                            // b가 kk번째를 골랐을 때
                            kk = k & -k;
                            if (jj&kk)        // 같은거라면 절반씩 먹으니 결국 bc[jj]의 총량만큼 충전가능
                                mv[0= max(mv[0], bc[jj].second);
                            else            // 다른거라면 서로가 고른 배터리 용량만큼 충전가능
                                mv[0= max(mv[0], bc[jj].second + bc[kk].second);
                        }
                    }
                }
                // 겹치는거 없음
                else {
                    // 각자 고를 수 있는 충전기중에 최대값만 고르면 된다
                    if (bc[j].first != tc) {
                        for (; j; j -= jj) {
                            jj = j & -j;
                            mv[0= max(mv[0], bc[jj].second);
                        }
                        j = map[ax][ay];
                        bc[j] = { tc, mv[0] };
                    }
                    if (bc[k].first != tc) {
                        mv[1= 0;
                        for (; k; k -= kk) {
                            kk = k & -k;
                            mv[1= max(mv[1], bc[kk].second);
                        }
                        k = map[bx][by];
                        bc[k] = { tc, mv[1] };
                    }
                    mv[0= bc[j].second + bc[k].second;
                }
                d[map[ax][ay]][map[bx][by]] = d[map[bx][by]][map[ax][ay]] = { tc,mv[0] };
            }
            ans += d[map[ax][ay]][map[bx][by]].second;
        }
        cout << "#" << tc << " " << ans << '\n';
    }
    return 0;
}
cs


'SWEA' 카테고리의 다른 글

4740. 밍이의 블록게임  (0) 2018.10.07
핀볼 런타임 에러나는 TC  (0) 2018.10.07
5648. 원자 소멸 시뮬레이션  (0) 2018.09.21
5658. 보물상자 비밀번호  (0) 2018.09.21
5656. 벽돌 깨기  (0) 2018.09.21

+ Recent posts