- bfs - 한번 홀수 짝수 구분을 명확히 해야 합니다. - 명확하게 k 에 대해서 정해주도록 합니다. |
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 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | /* 2221 홈방법서비스 제공받는 집들은 각각 M의 비용 지불, 최대한 많은 집에 홈방법 서비스를 제공 K는 1이상의 정수입니다. K를 늘려가면서 검사를 진행하도록 합니다. K는 얼마까지 커질 수 있는지? K의 가장 큰 값은 K가 3일때 3*3까지 커버가 가능합니다. 맵이 3*3 이면 K는 3*3 까지 검사하도록 합니다. 1. k 를 1부터 K까지 선정하고, // 맵을 넘어가는 경우 예외처리 주의. 2. 2중 포문을 돌려서 그 안의 집의 숫자를 계산합니다. 3. 회사가 이익이 나는지 확인을 하도록 합니다. 회사가 이익이 남는 케이스 중에서 집의 수자가 가장 많은 집의 수를 출력합니다. */ #include <iostream> #include <algorithm> #include <queue> using namespace std; #define SIZE 25 int map[SIZE][SIZE]; int N, M; int maxVal; struct point { int x, y; }; queue<point> que; int visit[SIZE][SIZE]; int x, y, nx, ny; int cost; int home_cnt; int dx[] = { 0,0,1,-1 }; int dy[] = { 1,-1,0,0 }; int repeat_cnt; int total_home_cnt; void problemIn() { cin >> N >> M; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { cin >> map[i][j]; if (map[i][j] == 1) { total_home_cnt++; } } } } void init() { maxVal = 0; total_home_cnt = 0; repeat_cnt = 0; cost = 0; for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { map[i][j] = 0; } } } void visit_init() { for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { visit[i][j] = 0; } } } void bfs(int k) { home_cnt = 0; repeat_cnt = 0; if (map[que.front().x][que.front().y] == 1) home_cnt++; while (!que.empty()) { if (repeat_cnt == (k - 1)) { while (!que.empty()) que.pop(); return; } int qlen = que.size(); while (qlen--) { x = que.front().x; y = que.front().y; que.pop(); for (int i = 0; i < 4; i++) { nx = x + dx[i]; ny = y + dy[i]; if (nx < 0 || ny < 0 || nx >= N || ny >= N) continue; if (visit[nx][ny] == 0) { if (map[nx][ny] == 1) home_cnt++; visit[nx][ny] = 1; que.push({ nx,ny }); } } } repeat_cnt++; } } /* k 에 대해서 가지치기를 해보도록 합니다. K = 2 일떄 운용비용은 5 입니다. 커버 하는 지역은 5군데 입니다. K = 3 운영비용 13 입니다. 커버 하는 지역 13입니다. 처음에 집의 개수를 구하고, 그것을 비용을 커버할 수 있는 K 까지만 하면 되겠습니다. 예를 들어서 3*3 맵에서 집이 1개이고 지불비용이 5입니다. 그럼 케이는 케이는 5까지만 가능합니다. 최대지불비용과 케이의 운영비용을 비교합니다. */ void solve() { //total_home_cnt * M; for (int k = 1; k <= N+1; k++) { cost = k*k + (k - 1)*(k - 1); if (total_home_cnt * M >= cost) { for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { visit[i][j] = 1; que.push({ i,j }); bfs(k); if ((home_cnt * M) - cost >= 0) { maxVal = max(maxVal, home_cnt); } visit_init(); } } } } } int main() { int T; cin >> T; for (int tc = 1; tc <= T; tc++) { problemIn(); solve(); cout << "#" << tc << " " << maxVal << endl; init(); } return 0; } | cs |