题意:
递归定义了k-quotation是k个分号+若干个(k-1)-quotataion+k个分号,然后给你很多个分号,叫你求一下最大是多少quotation。
思路:
对于一个k-quotation,分号的前缀形式肯定是(k)(k-1)(k-2)..(1)(1),然后后面可以考虑继续接(1)(1)或者接一个(2)。因此,可以先枚举quotation为k,从后往前dp。dp[i][j][t] 表示考虑a[i]第j个以及后面的分号,它的前面是有一个(t - 1)的分号,能不能构成满足条件的分法。有两种转移,一种是再接一个(t-1)-quotation,也就是(t-1)(t-2)...(1)(1),或者是结束这个(t-1)-quotation,加上一个(t)。
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pii pair<int, int>
#define MP make_pair
#define inf 0x3f3f3f3f
#define mod 1000000007
#define eps 1e-12
#define Pi acos(-1.0)
#define N 110
#define M 200020
#define PB push_back
#define MP make_pair
#define fi first
#define se second
bool dp[N][N][N];
pii f[N][N][N];
int n, a[N];
pii calc(int x, int y, int t) {
pii ret(-1, -1);
for(int i = t; i >= 1; --i) {
if(y + i - 1 > a[x]) return ret;
y += i;
if(y > a[x]) x++, y = 1;
if(x > n) return ret;
}
y++;
if(y > a[x]) x++, y = 1;
return MP(x, y);
}
pii jump(int x, int y, int t) {
if(y + t - 1 > a[x]) return MP(-1, -1);
y += t;
if(y > a[x]) x++, y = 1;
return MP(x, y);
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= a[i]; ++j) {
for(int t = 1; t <= 100; ++t) {
f[i][j][t] = calc(i, j, t);
}
}
}
int ans = 0;
for(int k = 1; k <= 100; ++k) {
if(f[1][1][k].fi == -1) continue;
memset(dp[n + 1][1], 0, sizeof dp[n + 1][1]);
dp[n + 1][1][k] = 1;
int dx = f[1][1][k].fi;
int dy = f[1][1][k].se;
for(int i = n; i >= dx; --i) {
for(int j = a[i]; j >= 1; --j) {
for(int t = k - 1; t >= 1; --t) {
pii p = jump(i, j, t + 1);
dp[i][j][t] = 0;
if(p.fi != -1) {
dp[i][j][t] |= dp[p.fi][p.se][t + 1];
}
if(f[i][j][t].fi != -1) {
int xx = f[i][j][t].fi;
int yy = f[i][j][t].se;
dp[i][j][t] |= dp[xx][yy][1];
}
}
}
}
if(dp[dx][dy][1]) ans = max(ans, k);
}
if(ans == 0) puts("no quotation");
else printf("%d\n", ans);
return 0;
}