diff --git a/P4342.cpp b/P4342.cpp new file mode 100644 index 0000000..060d16d --- /dev/null +++ b/P4342.cpp @@ -0,0 +1,61 @@ +#include +using namespace std; +int n; +char op[105]; +long long a[105]; +long long f[105][105]; +long long g[105][105]; +void getc(char &c) { + c = getchar_unlocked(); + while(c != 't' && c != 'x') c = getchar_unlocked(); +} +int main() { + scanf("%d", &n); + for (int i = 1; i <= n; ++i) { + getc(op[i]); + scanf("%lld", &a[i]); + a[i + n] = a[i]; + op[i + n] = op[i]; + } + for (int i = 1; i <= 2 * n; ++i) { + f[i][i] = a[i]; + g[i][i] = a[i]; + } + for (int len = 2; len <= n; ++len) { + for (int l = 1; l + len - 1 <= 2 * n; ++l) { + int r = l + len - 1; + f[l][r] = LLONG_MIN; + g[l][r] = LLONG_MAX; + for (int k = l; k < r; ++k) { + char o = op[k + 1]; + if (o == 't') { + f[l][r] = max(f[l][r], f[l][k] + f[k + 1][r]); + g[l][r] = min(g[l][r], g[l][k] + g[k + 1][r]); + } else { + long long v1 = f[l][k] * f[k + 1][r]; + long long v2 = f[l][k] * g[k + 1][r]; + long long v3 = g[l][k] * f[k + 1][r]; + long long v4 = g[l][k] * g[k + 1][r]; + f[l][r] = max({f[l][r], v1, v2, v3, v4}); + g[l][r] = min({g[l][r], v1, v2, v3, v4}); + } + } + } + } + long long ans = LLONG_MIN; + vector anss; + for (int l = 1; l <= n; ++l) { + int r = l + n - 1; + // printf("%lld\n", f[l][r]); + if (f[l][r] > ans) { + ans = f[l][r]; + anss.clear(); + anss.push_back(l); + } else if(f[l][r] == ans) { + anss.push_back(l); + } + } + printf("%lld\n", ans); + for(int i:anss) printf("%d ", i); + return 0; +} \ No newline at end of file diff --git a/P4342.md b/P4342.md new file mode 100644 index 0000000..3dddd6f --- /dev/null +++ b/P4342.md @@ -0,0 +1,60 @@ +# P4342 [IOI 1998] Polygon + +## 题目描述 + +**题目可能有些许修改,但大意一致。** + +Polygon 是一个玩家在一个有 $n$ 个顶点的多边形上玩的游戏,如图所示,其中 $n = 4$。每个顶点用整数标记,每个边用符号 `+`(加)或符号 `*`(乘积)标记。 + +![](https://cdn.luogu.org/upload/pic/16086.png) + +第一步,删除其中一条边。随后每一步: + +选择一条边连接的两个顶点 $V_1$ 和 $V_2$,用边上的运算符计算 $V_1$ 和 $V_2$ 得到的结果来替换这两个顶点。 + +游戏结束时,只有一个顶点,没有多余的边。 + +如图所示,玩家先移除编号为 $3$ 的边。之后,玩家选择计算编号为 $1$ 的边,然后计算编号为 $4$ 的边,最后,计算编号为 $2$ 的边。结果是 $0$。 + +边的编号规则为:第 $i$ 条边连接编号为 $i-1$ 和编号为 $i$ 的点。特别地,第 $1$ 条边连接编号为 $1$ 和编号为 $n$ 的点 + +![](https://cdn.luogu.org/upload/pic/16088.png) + +(译者注:这里每条边的运算符旁边的数字为边的编号,不拿来计算) + +最终剩余的点的数值即为得到的分数。 + +编写一个程序,给定一个多边形,计算最高可能的分数。 + +## 输入格式 + +输入描述一个有 $n$ 个顶点的多边形,它包含两行。第一行是数字 $n$,为总边数。 + +第二行描述这个多边形,一共有 $n$ 组,每组中第一个字符为边 $i$ 的计算符号(`t` 代表相加,`x` 代表相乘),第二个代表顶点 $i$ 上的数字。多边形首尾相连。 + +## 输出格式 + +第一行,输出最高的分数。在第二行,对于每一条边,输出这条边当且仅当在删除这条边后,能够通过操作得到所有可能情况中的最高分,以严格升序输出。 + +## 输入输出样例 #1 + +### 输入 #1 + +``` +4 +t -7 t 4 x 2 x 5 + +``` + +### 输出 #1 + +``` +33 +1 2 +``` + +## 说明/提示 + +保证 $3 \le n \le 50$。 + +对于任何一系列的操作,顶点数字都在 $[-32768,32767]$ 的范围内。 \ No newline at end of file