题面链接
https://www.acwing.com/problem/content/description/285/
思路
题目给出一个多边形,边为运算符,顶点为数值,所求为删去一条边之后,通过不断合并边可以获得的最大值。
乍一看,删去哪一条边获取最大值是未知的,需要枚举每一条边。
枚举之后,原来的多边形退化为一条链,问题变成一个类似石子合并(https://www.acwing.com/problem/content/284/)的问题,大致方向就是区间DP,阶段更新就是区间的长度。问题变为,如何确定满足无后效性以及最优子结构性质的状态。
由于运算符中存在乘法,故而不能将状态设计为最大值,因为一个负的最大值和一个正的最大值的乘积可能是一个很小的值。因此,还需要设计一个最小值状态,在乘法更新的时候,需要枚举最大值、最小值相乘的四种情况。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| #include <bits/stdc++.h> using namespace std;
const int N = 55; const int INF = 0x3f3f3f3f; const int NINF = -0x3f3f3f3f; const int ADD = 0; const int MUL = 1; int dp_max[N][N]; int dp_min[N][N];
int val[N]; int op[N];
int solve(int start, int tot){ for(int i=0;i<N;i++){ for(int j=0;j<N;j++){ dp_max[i][j]=NINF; dp_min[i][j]=INF; } } for(int len = 1;len<=tot;len++){ for(int l=0;l+len-1<tot;l++){ int r = l+len-1; int _l = (l+start)%tot; if (len==1){ dp_max[l][r] = val[_l]; dp_min[l][r] = val[_l]; continue; } for(int k=l; k<r; k++){ int _op = op[(k+1+start)%tot]; if (_op==ADD){ dp_max[l][r] = max(dp_max[l][r], dp_max[l][k]+dp_max[k+1][r]); dp_min[l][r] = min(dp_min[l][r], dp_min[l][k]+dp_min[k+1][r]); continue; } if (_op==MUL){ int MM = dp_max[l][k]*dp_max[k+1][r]; int Mm = dp_max[l][k]*dp_min[k+1][r]; int mM = dp_min[l][k]*dp_max[k+1][r]; int mm = dp_min[l][k]*dp_min[k+1][r]; dp_max[l][r] = max(dp_max[l][r],max(MM,max(Mm,max(mM,mm)))); dp_min[l][r] = min(dp_min[l][r], min(MM,min(Mm,min(mM,mm)))); } } } } return dp_max[0][tot-1]; }
int main(){ int tot; cin>>tot; for(int i=0;i<tot;i++){ char ch; cin>>ch; op[i] = (ch=='t')?ADD:MUL; cin>>val[i]; } vector<int> ans_set; int max_val=NINF; for(int i=0;i<tot;i++){ int tem_val = solve(i,tot); if(tem_val>max_val){ max_val = tem_val; ans_set.clear(); ans_set.push_back(i+1); }else if(tem_val == max_val){ ans_set.push_back(i+1); } } cout<<max_val<<endl; for(auto i:ans_set){ cout<<i<<" "; } cout<<endl; return 0; }
|
感谢阅读!欢迎评论嗷~