#include using namespace std; ifstream fin("catsdogs.in"); ofstream fout("catsdogs.out"); stringstream trash; //// Submit #define cin fin #define cout fout #define debug trash //#define debug cout typedef pair pii; typedef pair pdi; #define x first #define y second const int maxn = 105, maxk = 505, inf = 1e9, dead = 1e4 + 4; const double weight = 1.85; int f, cats; char c[maxn][maxn][maxn]; int h[maxn]; int w[maxn]; int bonus[maxn]; double best[2][maxn][maxk]; bool used[maxn][maxk]; int val[maxn][maxn]; int col[2][maxn][maxn]; pii fro[maxn][maxn]; int bio[maxn][maxn]; int bio2[maxn][maxn]; int dep[maxn][maxn]; int piv[maxn][maxn]; vector tiles[2][maxn * maxn]; double sum[maxn * maxn]; int par[2][maxn * maxn]; int len[2][maxn * maxn]; double dp[maxn][maxk]; int recon[maxn][maxk]; int recon2[maxn][maxk]; bool recon3[maxn][maxk]; int dx[] = {0, 1, 0, -1}; int dy[] = {1, 0, -1, 0}; string ds[] = {"R", "D", "L", "U"}; string db[] = {"L", "U", "R", "D"}; int dsu(int id, int x){ if(x == par[id][x]){ return x; } return par[id][x] = dsu(id, par[id][x]); } void dsumerge(int id, int x, int y, bool left = false){ x = dsu(id, x); y = dsu(id, y); if(x != y){ if(left){ par[id][y] = x; }else{ par[id][x] = y; } } } void reset(){ for(int i = 0; i < maxn; i++){ for(int j = 0; j < maxn; j++){ val[i][j] = 0; col[0][i][j] = 0; col[1][i][j] = 0; bio[i][j] = 0; dep[i][j] = 0; bio2[i][j] = 0; piv[i][j] = 0; fro[i][j] = pii(0, 0); } } for(int i = 0; i < maxn * maxn; i++){ tiles[0][i].clear(); tiles[1][i].clear(); sum[i] = 0; par[0][i] = 0; par[1][i] = 0; len[0][i] = 0; len[1][i] = 0; } } string s, z; void dfs1(int id, int x, int y, int n, int m, bool b){ bio[x][y] = id; int nx, ny; for(int i = 0; i < 4; i++){ if(b && piv[x][y] == i) continue; nx = x + dx[i]; ny = y + dy[i]; if(nx >= 1 && nx <= n && ny >= 1 && ny <= m && dsu(0, col[0][nx][ny]) == id && bio[nx][ny] != id){ s += ds[i]; dfs1(id, nx, ny, n, m, b && (i == piv[x][y])); if(!(b && (i == piv[x][y]))) s += db[i]; } } if(b){ int i = piv[x][y]; nx = x + dx[i]; ny = y + dy[i]; if(nx >= 1 && nx <= n && ny >= 1 && ny <= m && dsu(0, col[0][nx][ny]) == id && bio[nx][ny] != id){ s += ds[i]; dfs1(id, nx, ny, n, m, b && (i == piv[x][y])); if(!(b && (i == piv[x][y]))) s += db[i]; } } } int dfs2(int id, int x, int y, int n, int m){ bio2[x][y] = id; int nx, ny, mx = 0; for(int i = 0; i < 4; i++){ nx = x + dx[i]; ny = y + dy[i]; if(nx >= 1 && nx <= n && ny >= 1 && ny <= m && dsu(0, col[0][nx][ny]) == id && bio2[nx][ny] != id){ dep[nx][ny] = dep[x][y] + 1; int d = dfs2(id, nx, ny, n, m); if(d > mx){ mx = d; piv[x][y] = i; } } } return max(mx, dep[x][y]); } void print(int id, int n, int m){ z = ""; pii r; int d = min(int(tiles[0][id].size()), 100); for(int i = 0; i < d; i++){ s.clear(); for(pii p : tiles[0][id]){ bio[p.x][p.y] = bio2[p.x][p.y] = 0; } pii p = tiles[0][id][rand() % tiles[0][id].size()]; dfs2(id, p.x, p.y, n, m); dfs1(id, p.x, p.y, n, m, true); if(z.size() == 0 || s.size() < z.size()){ z = s; r = p; } } if(z == ""){ z = "STAY"; } cout << r.x << ' ' << r.y << '\n'; cout << z << '\n'; } void solve(int id, int n, int m, bool printing = false, int dogs = 1, bool del = false){ pii e = pii(0, 0); if(printing && dogs == 0){ return; } for(int i = 1; i <= n; i++){ for(int j = 1; j <= m; j++){ if(c[id][i][j] == '#'){ val[i][j] = -1; }else if(c[id][i][j] != '.'){ val[i][j] = c[id][i][j] - '1' + 1; } if(e == pii(0, 0) && c[id][i][j] != '#'){ e = pii(i, j); } } } int cnt = 0; double total = 0; set > reg; queue q; par[0][dead] = dead; par[1][dead] = dead; for(int i = 1; i <= n; i++){ for(int j = 1; j <= m; j++){ if(val[i][j] >= 1){ cnt++; col[0][i][j] = cnt; col[1][i][j] = cnt; par[0][cnt] = cnt; par[1][cnt] = cnt; sum[cnt] = 2 * val[i][j]; total += sum[cnt]; len[0][cnt]++; len[1][cnt]++; reg.insert(pdi(sum[cnt], cnt)); q.push(i); q.push(j); } } } if(cnt <= cats){ best[del][id][cnt] = total + bonus[id]; } int x, y, nx, ny, z, nz, mx, my, mz, ox, oy, ok = 1, w; while(!q.empty() && cnt > dogs){ x = q.front(); q.pop(); y = q.front(); q.pop(); for(int i = 0; i < 4 && cnt > dogs && (z = dsu(1, col[1][x][y])) != dead; i++){ nx = x + dx[i]; ny = y + dy[i]; nz = dsu(1, col[1][nx][ny]); if(nz != dead && nx >= 1 && nx <= n && ny >= 1 && ny <= m && val[nx][ny] != -1 && z != nz){ if(nz == 0){ fro[nx][ny] = pii(x, y); col[1][nx][ny] = z; q.push(nx); q.push(ny); }else{ mx = x; my = y; mz = z; if(rand() & 1){ swap(nx, mx); swap(ny, my); swap(nz, mz); } pii p; double dis = weight; ox = nx; oy = ny; while(dsu(0, col[0][ox][oy]) == 0){ dis += weight; p = fro[ox][oy]; ox = p.x; oy = p.y; } ox = mx; oy = my; while(dsu(0, col[0][ox][oy]) == 0){ dis += weight; p = fro[ox][oy]; ox = p.x; oy = p.y; } w = reg.begin()->y; if(del && dis >= sum[w] && true){ dsumerge(0, w, dead, false); dsumerge(1, w, dead, false); total -= sum[w]; cnt--; ok = false; if(cnt <= cats){ best[del][id][cnt] = total; } reg.erase(reg.begin()); }else{ ox = nx; oy = ny; while(dsu(0, col[0][ox][oy]) == 0){ col[0][ox][oy] = nz; len[0][nz]++; p = fro[ox][oy]; ox = p.x; oy = p.y; } ox = mx; oy = my; while(col[0][ox][oy] == 0){ col[0][ox][oy] = mz; len[0][mz]++; p = fro[ox][oy]; ox = p.x; oy = p.y; } reg.erase(reg.find(pdi(sum[nz], nz))); reg.erase(reg.find(pdi(sum[mz], mz))); sum[mz] += sum[nz] - dis; reg.insert(pdi(sum[mz], mz)); total -= dis; cnt--; if(cnt <= cats){ best[del][id][cnt] = total + bonus[id] * ok; } len[0][mz] += len[0][nz]; len[1][mz] += len[1][nz]; dsumerge(0, nz, mz, false); dsumerge(1, nz, mz, false); } if(printing && cnt == dogs){ break; } } } } } for(int i = 1; i <= n; i++){ for(int j = 1; j <= m; j++){ if(val[i][j] != -1){ tiles[0][dsu(0, col[0][i][j])].push_back(pii(i, j)); }else{ // debug << '#'; } } } vector vreg; for(pdi p : reg){ vreg.push_back(p); } reverse(vreg.begin(), vreg.end()); if(printing){ for(int i = 0; i < dogs; i++){ cout << id + 1 << '\n'; print(dsu(0, vreg[i].y), n, m); } for(int i = vreg.size(); i < dogs; i++){ cout << id + 1 << '\n'; cout << e.x << ' ' << e.y << '\n'; cout << "STAY\n"; } }else{ for(int i = 1; i < min(int(vreg.size()), cats); i++){ best[del][id][i] = best[del][id][i - 1] + vreg[i - 1].x; } for(int i = 1; i <= cats; i++){ best[del][id][i] = max(best[del][id][i], best[del][id][i - 1]); } if(del){ for(int i = 1; i <= cats; i++){ if(best[1][id][i] >= best[0][id][i]){ best[0][id][i] = best[1][id][i]; used[id][i] = true; } } } } reset(); } int main(){ ios_base::sync_with_stdio(false); cin >> f >> cats; for(int i = 0; i < f; i++){ cin >> h[i] >> w[i] >> bonus[i]; for(int j = 1; j <= h[i]; j++){ for(int k = 1; k <= w[i]; k++){ cin >> c[i][j][k]; } } } for(int i = 0; i < f; i++){ solve(i, h[i], w[i], false, 1, false); solve(i, h[i], w[i], false, 1, true); } for(int i = f - 1; i >= 0; i--){ for(int j = 0; j <= cats; j++){ if(j){ dp[i][j] = dp[i][j - 1]; recon[i][j] = recon[i][j - 1] + 1; recon2[i][j] = 0; recon3[i][j] = false; } for(int k = 0; k <= j; k++){ if(dp[i][j] < dp[i + 1][j - k] + best[0][i][k]){ dp[i][j] = dp[i + 1][j - k] + best[0][i][k]; recon[i][j] = k; recon2[i][j] = 1; recon3[i][j] = used[i][k]; } } } } debug << dp[0][cats] << endl; int cnt = cats; for(int i = 0; i < f && cnt > 0; i += recon2[i][cnt]){ solve(i, h[i], w[i], true, recon[i][cnt], recon3[i][cnt]); cnt -= recon[i][cnt]; } return 0; }