#include #include #include #include #include #include using std::sort; using std::cin; using std::cout; using std::endl; using std::vector; using std::map; using std::pair; using std::string; using std::make_pair; time_t TL = 4900; time_t curTime; struct Front{ int dots = 0; int n, m, b, ind; char bf[101][101]; } fronts[101]; struct Answer{ int ind; int x, y; int score; string mvs; const Answer& operator =(const Answer &a) { this->ind = a.ind; this->x = a.x; this->y = a.y; this->score = a.score; this->mvs = a.mvs; } } BestAnswer, ans1; bool cmp(Front a, Front b) { return a.dots <= b.dots; } int f, k, allc; int allC[101]; int isCat[10001]; bool hasDC[10001]; bool visited[10001]; int DepPar[10001][2]; vector stP; vector graph[10001]; vector< pair< int, pair > > roads; map< pair, char > mv; string ans = ""; bool used[10001]; void Go(int i) { used[i] = true; for(int j=0; j < graph[i].size(); j++) if(!used[graph[i][j]]) Go(graph[i][j]); } int GetComp(){ int ret = 0; for(int i = 0; i < stP.size(); i++) if(!used[stP[i]]) Go(stP[i]), ret++; for(int i = 0; i < 10001; i++) used[i] = false; return ret; } int Find(int a) { while(DepPar[a][1] != a) a = DepPar[a][1]; return a; } void Unite(int a, int b) { if(DepPar[a][0] > DepPar[b][0]) DepPar[b][1] = DepPar[a][1]; else if(DepPar[b][0] > DepPar[a][0]) DepPar[a][1] = DepPar[b][1]; else DepPar[b][1] = DepPar[a][1], DepPar[a][0]++; } void BuildGraph(int i, bool inp) { stP.clear(); roads.clear(); mv.clear(); for(int j = 0; j < 10000; j++) isCat[j] = 0, graph[j].clear(); for(int j = 0; j < 10000; j++) DepPar[j][0] = 0, DepPar[j][1] = j; for(int j = 0; j < fronts[i].n; j++) { for(int q = 0; q < fronts[i].m; q++) { if(fronts[i].bf[j][q] == '#') continue; if(fronts[i].bf[j][q] != '.') { stP.push_back(j*fronts[i].m + q); isCat[j*fronts[i].m + q] = fronts[i].bf[j][q] - '0'; } if(j > 0 and fronts[i].bf[j-1][q] != '#') { int val = 2; if(fronts[i].bf[j-1][q] != '.') val--; if(fronts[i].bf[j][q] != '.') val--; mv[make_pair(j*fronts[i].m + q, (j-1)*fronts[i].m + q)] = 'U'; mv[make_pair((j-1)*fronts[i].m + q, j*fronts[i].m + q)] = 'D'; roads.push_back(make_pair(val, make_pair(j*fronts[i].m + q, (j-1)*fronts[i].m + q))); } if(j < fronts[i].n-1 and fronts[i].bf[j+1][q] != '#') { int val = 2; if(fronts[i].bf[j+1][q] != '.') val--; if(fronts[i].bf[j][q] != '.') val--; mv[make_pair(j*fronts[i].m + q, (j+1)*fronts[i].m + q)] = 'D'; mv[make_pair((j+1)*fronts[i].m + q, j*fronts[i].m + q)] = 'U'; roads.push_back(make_pair(val, make_pair(j*fronts[i].m + q, (j+1)*fronts[i].m + q))); } if(q > 0 and fronts[i].bf[j][q-1] != '#') { int val = 2; if(fronts[i].bf[j][q-1] != '.') val--; if(fronts[i].bf[j][q] != '.') val--; mv[make_pair(j*fronts[i].m + (q-1), j*fronts[i].m + q)] = 'R'; mv[make_pair(j*fronts[i].m + q, j*fronts[i].m + (q-1))] = 'L'; roads.push_back(make_pair(val, make_pair(j*fronts[i].m + (q-1), j*fronts[i].m + q))); } if(q < fronts[i].m-1 and fronts[i].bf[j][q+1] != '#') { int val = 2; if(fronts[i].bf[j][q+1] != '.') val--; if(fronts[i].bf[j][q] != '.') val--; mv[make_pair(j*fronts[i].m + q, j*fronts[i].m + (q+1))] = 'R'; mv[make_pair(j*fronts[i].m + (q+1), j*fronts[i].m + q)] = 'L'; roads.push_back(make_pair(val, make_pair(j*fronts[i].m + q, j*fronts[i].m + (q+1)))); } } } sort(roads.begin(), roads.end()); int c_ = stP.size(); pair a; for(int j = 0; j < (signed int)roads.size(); j++) { a.first = Find(roads[j].second.first); a.second = Find(roads[j].second.second); if(a.first != a.second){ graph[roads[j].second.first].push_back(roads[j].second.second); graph[roads[j].second.second].push_back(roads[j].second.first); Unite(a.first, a.second); if(roads[j].first == 0) { c_--; continue; } if(inp) continue; int cnt_1 = 0, cnt_2 = 0; for(int q = 0; q < stP.size(); q++) { int temp = Find(stP[q]); if(temp == a.first) cnt_1++; if(temp == a.second) cnt_2++; } if(cnt_1 >= 1 and cnt_2 >= 1) c_--; if(c_ - allC[i] + allc <= k) { allc += (c_ - allC[i]); break; } } } } int asize; void Clear(int node, int par, int d) { visited[node] = true; for(int i = 0; i < (signed int)graph[node].size(); i++) { if(visited[graph[node][i]] == false) { ans += mv[make_pair(node, graph[node][i])]; if(isCat[graph[node][i]]) asize = ans.size(), ans1.score += isCat[graph[node][i]] + 1; Clear(graph[node][i], node, d+1); if((signed int)graph[graph[node][i]].size() == 1 and isCat[graph[node][i]] == 0) { graph[node].erase(graph[node].begin() + i); i--; ans.erase(ans.size() - 2, 2); } } } ans += mv[make_pair(node, par)]; } vector all[10001]; pair > scores[10001]; int ansCnt; int dogs = 0; void GetBestAns() { sort(scores, scores + ansCnt); dogs = k; for(int i = ansCnt-1; i >= 0; i--) { if(dogs - scores[i].second.first >= 0) { for(int j = 0; j < all[scores[i].second.second].size(); j++) { cout << all[scores[i].second.second][j].ind << endl; cout << all[scores[i].second.second][j].x << " " << all[scores[i].second.second][j].y << endl; cout << all[scores[i].second.second][j].mvs << endl; } dogs -= scores[i].second.first; } else { for(int j = 0; j < dogs ; j++) { cout << all[scores[i].second.second][j].ind << endl; cout << all[scores[i].second.second][j].x << " " << all[scores[i].second.second][j].y << endl; cout << all[scores[i].second.second][j].mvs << endl; } exit(0); } } for(int j = 0; j < dogs; j++) cout << 0 << endl; exit(0); } void ClearFront(int indx) { ans = ""; ans1.score = 0; dogs = 0; for(int i = 0; i < (signed int)stP.size(); i++) { if(!visited[stP[i]] and isCat[stP[i]]) { ans1.score += isCat[stP[i]]; Clear(stP[i], stP[i], 0); ans1.ind = fronts[indx].ind; ans1.x = stP[i] / fronts[indx].m + 1; ans1.y = stP[i] % fronts[indx].m + 1; if(ans[0] < 'A' or ans[0] > 'Z') ans1.mvs = "STAY"; else { if(ans[ans.size() - 1]< 'A' or ans[ans.size() - 1] > 'Z') ans.erase(ans.size() - 1, 1); ans1.score -= asize / 2 + 1; ans1.mvs = ans.substr(0, asize); } int ii = 0; for(ii; ii < (signed int)stP.size(); ii++) if(!visited[stP[ii]]) break; if(ii == (signed int)stP.size()) ans1.score += fronts[indx].b; ans = ""; dogs++; all[ansCnt].push_back(ans1); scores[ansCnt].first += ans1.score; scores[ansCnt].second.first ++; scores[ansCnt].second.second = ansCnt; asize = 0; ans1.score = 0; //if(dogs == k) exit(0); } if(clock() - curTime >= TL) { GetBestAns(); } } scores[ansCnt].first = scores[ansCnt].first / scores[ansCnt].second.first; ansCnt++; for(int i = 0; i < 10000; i++) visited[i] = false; } void Clear1(int node, int par, int d) { visited[node] = true; for(int i = 0; i < (signed int)graph[node].size(); i++) { if(visited[graph[node][i]] == false) { ans += mv[make_pair(node, graph[node][i])]; if(isCat[graph[node][i]]) asize = ans.size(), ans1.score += isCat[graph[node][i]] + 1; Clear1(graph[node][i], node, d+1); if((signed int)graph[graph[node][i]].size() == 1 and isCat[graph[node][i]] == 0) { graph[node].erase(graph[node].begin() + i); i--; ans.erase(ans.size() - 2, 2); } } } ans += mv[make_pair(node, par)]; } void Clf1(int indx) { ans = ""; for(int i = 0; i < (signed int)stP.size(); i++) { if(!visited[stP[i]] and isCat[stP[i]]) { Clear1(stP[i], stP[i], 0); ans1.score -= asize/2 + 1; ans1.ind = fronts[indx].ind; ans1.x = stP[i] / fronts[indx].m + 1; ans1.y = stP[i] % fronts[indx].m + 1; if(ans[0] < 'A' or ans[0] > 'Z') ans1.mvs = "STAY"; else { if(ans[ans.size() - 1]< 'A' or ans[ans.size() - 1] > 'Z') ans.erase(ans.size() - 1, 1); ans1.mvs = ans.substr(0, asize); } int ii = 0; for(ii; ii < (signed int)stP.size(); ii++) if(!visited[stP[ii]]) break; if(ii == (signed int)stP.size() and i == 0) ans1.score += fronts[indx].b; if(BestAnswer.score < ans1.score) BestAnswer = ans1; ans = ""; ans1.score = 0; asize = 0; } } for(int i = 0; i < 10000; i++) visited[i] = false; } void Solve1() { for(int j = 0; j < 10000; j++) graph[j].clear(); for(int i = 0; i < 10000; i++) DepPar[i][0] = 0, DepPar[i][1] = i; pair a; for(int i = 0; i < (signed int)roads.size(); i++) { a.first = Find(roads[i].second.first); a.second = Find(roads[i].second.second); if(a.first != a.second){ graph[roads[i].second.first].push_back(roads[i].second.second); graph[roads[i].second.second].push_back(roads[i].second.first); Unite(a.first, a.second); int comp = GetComp(); if(comp == k) break; } } ans = ""; for(int i = 0; i < (signed int)stP.size(); i++) { if(!visited[stP[i]] and isCat[stP[i]]) { cout << 1 << endl; cout << stP[i] / fronts[0].m + 1 << " " << stP[i] % fronts[0].m + 1 << endl; Clear(stP[i], stP[i], 0); if(ans[0] < 'A' or ans[0] > 'Z') cout << "STAY\n"; else { ans = ans.substr(0, asize); if(ans[ans.size() - 1]< 'A' or ans[ans.size() - 1] > 'Z') ans.erase(ans.size() - 1, 1); cout << ans << endl; } ans = ""; asize = 0; } } } void Solve() { sort(fronts, fronts + f, cmp); if(k == 1) { BestAnswer.score = 0; for(int i = f-1; i >=0; i--) { BuildGraph(i, true); Clf1(i); } cout << BestAnswer.ind << endl; cout << BestAnswer.x << " " << BestAnswer.y << endl; cout << BestAnswer.mvs << endl; exit(0); } if(f == 1) { BuildGraph(0, true); Solve1(); exit(0); } for(int i = f - 1; i >= 0; i--) { BuildGraph(i, false); ClearFront(i); } } void Input(){ cin >> f >> k; for(int i = 0; i < f; i++) { fronts[i].dots = 0; cin >> fronts[i].n >> fronts[i].m >> fronts[i].b; fronts[i].ind = i+1; for(int j = 0; j < fronts[i].n; j++) { for(int q = 0; q < fronts[i].m; q++) { cin >> fronts[i].bf[j][q]; if(fronts[i].bf[j][q] == '.') fronts[i].dots++; } } BuildGraph(i, true); allC[i] = GetComp(); allc += allC[i]; } } int main() { std::iostream::sync_with_stdio(false); cin.tie(NULL); curTime = clock(); //freopen("test.in", "r", stdin); //freopen("test1.in", "r", stdin); freopen("catsdogs.in", "r", stdin); freopen("catsdogs.out", "w", stdout); Input(); Solve(); GetBestAns();