#include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; constexpr int N = 100; constexpr int C = 26; vector> T(C); vector> D(C); int loss = 0; vector L(N); vector> pos(C); void setPos(int i, int r, int c) { L[pos[i].first][pos[i].second] = '.'; pos[i] = {r, c}; L[pos[i].first][pos[i].second] = 'A' + i; } constexpr int TC = 4; vector> dt[TC]; constexpr int FAR = INT_MAX / 4; void bfs(int i, vector>& d) { d.resize(N); for(int i = 0; i < N; ++i) { d[i].resize(N); fill(d[i].begin(), d[i].end(), FAR); } queue> Q; d[pos[i].first][pos[i].second] = 0; Q.push(pos[i]); while(!Q.empty()) { auto [r, c] = Q.front(); Q.pop(); for(auto [dr, dc] : array, 4>{{{-1, 0}, {1, 0}, {0, -1}, {0, 1}}}) { int r2 = r + dr; int c2 = c + dc; if(L[r2][c2] != '#' && d[r2][c2] == FAR) { d[r2][c2] = d[r][c] + 1; Q.push({r2, c2}); } } } for(int j = 0; j < C; ++j) { auto [r, c] = pos[j]; if(d[r][c] < 0) { throw 5; } D[i][j] = d[r][c]; } } void update() { vector threads; atomic nextIdx = 0; for(int ti = 0; ti < TC; ++ti) { threads.emplace_back([ti, &nextIdx]() { while(true) { int i = nextIdx.fetch_add(1); if(i >= C) { break; } bfs(i, dt[ti]); } }); } for(thread& t : threads) { t.join(); } loss = 0; for(int i = 0; i < C; ++i) { for(int j = 0; j < C; ++j) { if(D[i][j] >= FAR) { loss = FAR; return; } loss += abs(D[i][j] - T[i][j]); } } } int main() { cin.sync_with_stdio(false); cin.tie(nullptr); mt19937 rng; ifstream fp("laby.txt"); for(int i = 0; i < C; ++i) { T[i].resize(C); D[i].resize(C); for(int j = 0; j < C; ++j) { fp >> T[i][j]; } } if(!fp.good()) throw 5; for(int i = 0; i < N; ++i) { L[i].resize(N); for(int j = 0; j < N; ++j) { L[i][j] = (i == 0 || j == 0 || i == N - 1 || j == N - 1) ? '#' : '.'; } } if(C + 2 > N) throw 5; for(int i = 0; i < C; ++i) { pos[i] = {1, 1 + i}; L[pos[i].first][pos[i].second] = 'A' + i; } for(int iter = 0; ; ++iter) { int best = INT_MAX; vector> bestMoves; for(int i = 0; i < C; ++i) { auto [r, c] = pos[i]; for(int dr = -2; dr <= 2; ++dr) { for(int dc = -2; dc <= 2; ++dc) { int r2 = r + dr; int c2 = c + dc; if(r2 >= 1 && c2 >= 1 && r2 < N - 1 && c2 < N - 1 && L[r2][c2] == '.') { setPos(i, r2, c2); update(); if(loss < best) { best = loss; bestMoves.clear(); } if(loss == best) { bestMoves.push_back({true, i, r2, c2}); } } } } setPos(i, r, c); } for(int asd = 0; asd < ((iter < 1000) ? 0 : 100); ++asd) { int r = uniform_int_distribution(1, N - 2)(rng); int c = uniform_int_distribution(1, N - 2)(rng); if(L[r][c] == '#') { L[r][c] = '.'; update(); if(loss < best) { best = loss; bestMoves.clear(); } if(loss == best) { bestMoves.push_back({false, '.', r, c}); } L[r][c] = '#'; } if(L[r][c] == '.') { L[r][c] = '#'; update(); if(loss < best) { best = loss; bestMoves.clear(); } if(loss == best) { bestMoves.push_back({false, '#', r, c}); } L[r][c] = '.'; } } if(bestMoves.empty()) { throw 5; } auto [t, i, r2, c2] = bestMoves[uniform_int_distribution(0, (int)bestMoves.size() - 1)(rng)]; if(t) { setPos(i, r2, c2); } else { L[r2][c2] = (char)i; } update(); if(loss != best) { throw 5; } int asd = 0; int bsd = 0; for(int i = 0; i < C; ++i) { for(int j = 0; j < C; ++j) { if(T[i][j] == D[i][j]) { ++asd; } ++bsd; } } cerr << iter << " " << best << " " << 100.0 * (double)asd / (double)bsd << "\n"; if(iter % 100 == 0) { cerr << "SAVE\n"; ofstream fp("labyrintti.out"); for(int i = 0; i < N; ++i) { fp << L[i] << "\n"; } fp.close(); } } return 0; }