因为有乘法和除法,乘上一个负数时,最小值就变最大值了,所以我们要维护最小和最大两个值;
用dpmax[i][j]和dpmin[i][j],代表用了 j 个运算符走到 i 时的最大值和最小值。
dp[n][m]就是结果了
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
ll a[1005];
char f[10];
int t,n,m,k;
ll maxs,mins;
ll dpmax[1005][10];
ll dpmin[1005][10];
int main(){
ios::sync_with_stdio(false);
cin>>t;
while(t--){
cin>>n>>m>>k;
memset(dpmin,0,sizeof(dpmax));
memset(dpmax,0,sizeof(dpmin));
for(int i=0;i<=n;i++){
dpmax[i][0]=k;
dpmin[i][0]=k;
}
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=m;i++){
cin>>f[i];
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(i>=j){
if(f[j]=='+'){
maxs=max(dpmax[i-1][j-1]+a[i],dpmin[i-1][j-1]+a[i]);
mins=min(dpmin[i-1][j-1]+a[i],dpmax[i-1][j-1]+a[i]);
}
if(f[j]=='-'){
maxs=max(dpmax[i-1][j-1]-a[i],dpmin[i-1][j-1]-a[i]);
mins=min(dpmin[i-1][j-1]-a[i],dpmax[i-1][j-1]-a[i]);
}
if(f[j]=='*'){
maxs=max(dpmax[i-1][j-1]*a[i],dpmin[i-1][j-1]*a[i]);
mins=min(dpmin[i-1][j-1]*a[i],dpmax[i-1][j-1]*a[i]);
}
if(f[j]=='/'){
maxs=max(dpmax[i-1][j-1]/a[i],dpmin[i-1][j-1]/a[i]);
mins=min(dpmin[i-1][j-1]/a[i],dpmax[i-1][j-1]/a[i]);
}
dpmax[i][j]=max(maxs,dpmax[i-1][j]);
dpmin[i][j]=min(mins,dpmin[i-1][j]);
}
if(i==j){
dpmax[i][j]=maxs;
dpmin[i][j]=mins;
}
}
}
cout<<dpmax[n][m]<<endl;
}
return 0;
}
本文介绍了一种使用动态规划方法解决带有加减乘除运算的算术表达式求值问题的算法。通过维护最大值和最小值矩阵,确保在遇到负数乘法或除法时,能够正确更新表达式的最大值和最小值,从而得到最终的最优解。
170

被折叠的 条评论
为什么被折叠?



