思维模拟+暴力——icpc nwrrc 2019 K
Posted zsben991126
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了思维模拟+暴力——icpc nwrrc 2019 K相关的知识,希望对你有一定的参考价值。
这题思路上不是很难,但是写起来贼复杂(知道为什么没啥人过了)
其实这题难的不是A的面积有多大,而是确定A后怎么填充剩下的矩形
自己写的代码复制粘贴三百多行,贴上题解的得了
题解用拉伸的填充法把代码化简了好多。。
如果不需要最大化矩形A的面积,则可以用如下算法解决该问题。垂直拉伸每个字母,直到碰到另一个字母或王国的边界。这样,我们得到了一组完整的列。水平拉伸每一列,直到碰到另一个字母或王国的边界。
考虑如何最大化矩形A的面积。首先,找到包含字母A且不包含其他字母的最大面积的矩形。这是一个经典问题。
显然王国的其余部分仍可以按要求的方式分成矩形。因为我们可以将剩下的区域分为四个大矩形:矩形的A上,下,左,右侧(左上,左下,右上,右下可并到任意一个相邻的大矩形中)。
每个大矩形都包含至少一个字母(否则我们可以在相应的方向上放大矩形A)。对于剩下的四个大矩形分别采取最开始的算法即可。
#include <bits/stdc++.h> #define long long long int using namespace std; // @author: pashka void fill(vector<string> &a, int U, int B, int L, int R, char c) { for (int i = U; i < B; i++) { for (int j = L; j < R; j++) { a[i][j] = c; } } } char lower(char c) { if (c >= ‘A‘ && c <= ‘Z‘) { c = ‘a‘ + (c - ‘A‘); } return c; } void split(vector<string> &a, int U, int B, int L, int R) { for (int i = U + 1; i < B; i++) { for (int j = L; j < R; j++) { if (a[i][j] == ‘.‘) { a[i][j] = lower(a[i - 1][j]); } } } for (int i = B - 2; i >= U; i--) { for (int j = L; j < R; j++) { if (a[i][j] == ‘.‘) { a[i][j] = lower(a[i + 1][j]); } } } for (int i = U; i < B; i++) { for (int j = L + 1; j < R; j++) { if (a[i][j] == ‘.‘) { a[i][j] = lower(a[i][j - 1]); } } } for (int i = U; i < B; i++) { for (int j = R - 2; j >= L; j--) { if (a[i][j] == ‘.‘) { a[i][j] = lower(a[i][j + 1]); } } } } int main() { ios::sync_with_stdio(false); int n, m; cin >> n >> m; vector<string> a(n); for (int i = 0; i < n; i++) cin >> a[i]; int ar = -1, ac = -1; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (a[i][j] == ‘A‘) { ar = i; ac = j; } } } a[ar][ac] = ‘.‘; int maxS = -1; int bestL = -1; int bestR = -1; int bestU = -1; int bestB = -1; vector<int> up(m + 1); for (int i = 0; i < n; i++) { vector<pair<int, int>> s; for (int j = 0; j <= m; j++) { // cout << i << " " << j << " "; if (j == m || a[i][j] != ‘.‘) { up[j] = i + 1; } int x = j; while (!s.empty() && s.back().second < up[j]) { int L = s.back().first; int R = j; int U = s.back().second; int B = i + 1; if (U <= ar && ar < B && L <= ac && ac < R) { int S = (R - L) * (B - U); if (S > maxS) { maxS = S; bestL = L; bestR = R; bestU = U; bestB = B; } } x = s.back().first; s.pop_back(); } s.push_back({x, up[j]}); } } // cout << bestU << " " << bestB << " " << bestL << " " << bestR << " "; fill(a, bestU, bestB, bestL, bestR, ‘a‘); split(a, 0, bestU, 0, m); split(a, bestB, n, 0, m); split(a, bestU, bestB, 0, bestL); split(a, bestU, bestB, bestR, m); a[ar][ac] = ‘A‘; for (int i = 0; i < n; i++) { cout << a[i] << " "; } return 0; }
以上是关于思维模拟+暴力——icpc nwrrc 2019 K的主要内容,如果未能解决你的问题,请参考以下文章
2019ACM-ICPC沈阳网络赛-K-Guanguan's Happy water(思维+暴力)
2020年2月2日 ICPC2019徐州 现场赛C <3 numbers 思维题