传送门
这是一道环形DP,解决方法是“任意选择一个位置断开,复制形成2倍长度的链”。
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
typedef long long ll;
const ll INF = 1e18;
int n;
char opt[105];
ll num[105];
ll dp[105][105][2]; //dp[l][r][0], dp[l][r][1]分别表示区间最小,区间最大
int main(){
int n;
while(cin >> n){
for(int i = 1; i <= n; ++i){
cin >> opt[i-1];
cin >> num[i];
}
opt[n] = opt[0];
for(int i = n+1; i <= 2*n; ++i){
num[i] = num[i-n];
opt[i] = opt[i-n];
}
for(int i = 1; i <= 100; ++i)
for(int j = i; j <= 100; ++j){
dp[i][j][0] = INF;
dp[i][j][1] = -INF;
}
for(int i = 1; i <= 100; ++i){
dp[i][i][0] = dp[i][i][1] = num[i];
}
for(int len = 2; len <= n; ++len){
for(int l = 1; l+len-1 <= 2*n; ++l){
int r = l+len-1;
for(int mid = l; mid < r; ++mid){ //运算符的位置
if(opt[mid] == 't'){ //如果是加号
if(dp[l][mid][0] > -INF && dp[l][mid][0] < INF && dp[mid+1][r][0] > -INF && dp[mid+1][r][0] < INF)
dp[l][r][0] = min(dp[l][r][0], dp[l][mid][0]+dp[mid+1][r][0]); //最小加最小
if(dp[l][mid][1] > -INF && dp[l][mid][1] < INF && dp[mid+1][r][1] > -INF && dp[mid+1][r][1] < INF)
dp[l][r][1] = max(dp[l][r][1], dp[l][mid][1]+dp[mid+1][r][1]); //最大加最大
}
else if(opt[mid] == 'x'){ //如果是乘号
if(dp[l][mid][0]>-INF && dp[l][mid][0]<INF && dp[mid+1][r][0]>-INF && dp[mid+1][r][0]<INF && dp[l][mid][1]>-INF && dp[mid+1][r][1]<INF && dp[mid+1][r][1]>-INF && dp[l][mid][1]<INF){
dp[l][r][0] = min(dp[l][r][0], dp[l][mid][0]*dp[mid+1][r][0]); //最小乘最小
dp[l][r][0] = min(dp[l][r][0], dp[l][mid][1]*dp[mid+1][r][1]); //最大乘最大
dp[l][r][0] = min(dp[l][r][0], dp[l][mid][1]*dp[mid+1][r][0]); //最小乘最大
dp[l][r][0] = min(dp[l][r][0], dp[l][mid][0]*dp[mid+1][r][1]); //最大乘最小
dp[l][r][1] = max(dp[l][r][1], dp[l][mid][0]*dp[mid+1][r][0]); //最小乘最小
dp[l][r][1] = max(dp[l][r][1], dp[l][mid][1]*dp[mid+1][r][1]); //最大乘最大
dp[l][r][1] = max(dp[l][r][1], dp[l][mid][1]*dp[mid+1][r][0]); //最小乘最大
dp[l][r][1] = max(dp[l][r][1], dp[l][mid][0]*dp[mid+1][r][1]); //最大乘最小
}
}
}
}
}
ll ans = -INF;
vector<ll> v;
for(int l = 1; l <= n; ++l){
if(ans < dp[l][l+n-1][1]){
ans = dp[l][l+n-1][1];
v.clear();
v.push_back(l);
}
else if(ans == dp[l][l+n-1][1]){
v.push_back(l);
}
}
cout << ans << endl;
int len = v.size();
for(int i = 0; i < len; ++i)
cout << v[i] << " ";
cout << endl;
}
return 0;
}