P6946 [ICPC2018 WF] Go with the Flow 题解
updated on 2025.4.12: 感谢 @yellow_mt 提醒,已经将 49 行代码修改。
本代码需要开 -O2 优化通过。
考虑枚举行宽后模拟。
由于符合条件的行宽的范围为
首先,很容易在
得到每一行的空格的位置后,我们设
则可以得到如下转移表达式:
答案即为
但是这样开
同样,
故我们只用赋值两行中存有空格的
考虑到行宽在变化时
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 100;
const int MAXM = 3000;
char str[MAXN];
int n, len[MAXM], sum, maxx, cnt[MAXN * MAXM], ans, ansx, aa[MAXM], bb[MAXM];
int G[MAXM];
bool used[MAXN * MAXM];
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> str + 1;
len[i] = strlen(str + 1);
maxx = max(maxx, len[i]);
sum += len[i];
}
for (int gap = maxx; gap < sum + n; gap++) {
int maxx = 0;
int j = 1, Len = 0, eid1 = 0, eid = 0;
int len1 = 0, len2 = 0;
while (j <= n) {
++eid1;
while (Len + len[j] <= gap && j <= n) {
Len = Len + len[j] + 1;
if (Len + len[j + 1] <= gap && j < n) {
G[++eid] = Len;
bb[++len2] = Len;
int A = 0;
if (used[Len - 1]) A = max(A, cnt[Len - 1]);
if (used[Len]) A = max(A, cnt[Len]);
if (used[Len + 1]) A = max(A, cnt[Len + 1]);
cnt[Len] = A + 1;
maxx = max(maxx, cnt[Len]);
}
j++;
}
Len = 0;
for (int i = 1; i <= len1; i++) used[aa[i]] = false;
for (int i = 1; i <= len2; i++) used[bb[i]] = true;
len1 = len2;
for (int i = 1; i <= len2; i++) aa[i] = bb[i];
len2 = 0;
}
for (int i = 1; i <= len1; i++) used[aa[i]] = false;
for (int i = 1; i <= eid; i++) cnt[G[i]] = 0;
if (maxx > ans) {
ans = maxx;
ansx = gap;
}
}
cout << ansx << " " << ans << endl;
return 0;
}