初看这个题很复杂的样子,但其实还是比较好做的
因为涉及到环,所以我们在输入得到的串后面再补一个串即可
每次求长度为n的dp值即可
因为这里涉及到负数,所以要考虑到负负相乘得正的情况
因此在计算的过程中既要保存最大值,又要保存最小值
算法类似于矩阵连乘dp[i][j] = {dp[i][k] "+\*" dp[k+1][j]}
期间写错了好多个字符,导致wa了一次
0ms代码如下:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define MAXN 150
#define LL long long
#define INF 0x7fffffff
using namespace std;
LL a[MAXN], dp[MAXN][MAXN][2];
char ch[MAXN];
LL Operate_max(int x, int y, int z) {//计算x z之间以y断开的最大值
if(ch[y+1] == 't')
return dp[x][y][0]+dp[y+1][z][0];
else if(ch[y+1] == 'x')
return max(dp[x][y][1]*dp[y+1][z][1], dp[x][y][0]*dp[y+1][z][0]);
}
LL Operate_min(int x, int y, int z) {//计算x z之间以y断开的最小值
if(ch[y+1] == 't')
return dp[x][y][1]+dp[y+1][z][1];
else if(ch[y+1] == 'x')
return min(dp[x][y][1]*dp[y+1][z][1], dp[x][y][0]*dp[y+1][z][0]);
}
int main(void) {
int n, tmpn;
LL tmp1, tmp2;
while(scanf("%d", &n) != EOF) {
memset(dp, 0, sizeof(dp));//初始化
for(int i=1; i<=n; ++i) {
cin >> ch[i] >> a[i] ;//读入字符串用cin处理
ch[n+i] = ch[i];
a[n+i] = a[i];
dp[i][i][0] = dp[i][i][1] = a[i];
dp[n+i][n+i][0] = dp[n+i][n+i][1] = a[n+i];
}
//dp[i][j] = dp[i][k], ch[k+1], dp[k+1][j];
tmpn = n<<1;
for(int r=1; r<n; ++r) {
for(int i=1; i<=tmpn; ++i) {
int j = i+r;
if(j > tmpn)
break;
tmp1 = Operate_max(i, i, j);
tmp2 = Operate_min(i, i, j);
dp[i][j][0] = max(tmp1, tmp2);
dp[i][j][1] = min(tmp1, tmp2);
for(int k=i+1; k<j; ++k) {
tmp1 = Operate_max(i, k, j);
tmp2 = Operate_min(i, k, j);
dp[i][j][0] = max(dp[i][j][0], max(tmp1, tmp2));
dp[i][j][1] = min(dp[i][j][1], min(tmp1, tmp2));
}
//printf("%d - %d\t %lld\t%lld\n", i, j, dp[i][j][0], dp[i][j][1]);
}
}
LL ans = max(dp[1][n][0], dp[1][n][1]);
for(int i=2; i<=n; ++i) {
ans = max(ans, dp[i][i+n-1][0]);
//ans = max(ans, dp[i][i+n-1][1]);
}
cout << ans << endl;
for(int i=1; i<=n; ++i) {
if(ans == dp[i][i+n-1][0]) {
//从i处开始长度为n的dp最大值等于最后的结果,则一定从i-1处先断开,因为下标从1开始,所以输出i
printf("%d ", i);
}
}
puts("");
}
return 0;
}