题意
有n个数和m个运算符,按顺序选m个数进行运算,初值为k,问最后能得到的最大值是多少。
思路
dp[i][j]表示选到了第i个数时用了j个运算符,观察发现,一个数只能由他前一个状态的最大值或最小值转移过来(因为乘上一个负数会使最小的数变最大),所以我们同时维护最大最小。
然后转移就行了,需要注意$i-1>j$时是不合法的状态。
转移方程:$dp[i][j]=max(dp[i-1][j-1]circ now[i],dp[i-1][j])(i<j)$
代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 const long long INF=0x3f3f3f3f3f3f3f3f; 4 long long dpmax[1005][6]; 5 long long dpmin[1005][6]; 6 long long room[1005]; 7 int main() 8 { 9 int T; 10 scanf("%d",&T); 11 while(T--) 12 { 13 long long n,m,k; 14 scanf("%lld%lld%lld",&n,&m,&k); 15 for(int i=1;i<=n;i++) 16 scanf("%lld",&room[i]); 17 char op[10]; 18 scanf("%s",op+1); 19 memset(dpmax,0,sizeof(dpmax)); 20 memset(dpmin,0,sizeof(dpmin)); 21 dpmax[0][0]=k; 22 dpmin[0][0]=k; 23 for(int i=1;i<=n;i++) 24 { 25 for(int j=0;j<=m;j++) 26 { 27 if(j==0) 28 dpmax[i][j]=k,dpmin[i][j]=k; 29 else{ 30 long long temp=dpmax[i-1][j-1],temp2=dpmin[i-1][j-1]; 31 long long maxx,minn; 32 if(op[j]=='+') 33 { 34 maxx=max(temp+room[i],temp2+room[i]); 35 minn=min(temp+room[i],temp2+room[i]); 36 } 37 else if(op[j]=='-') 38 { 39 maxx=max(temp-room[i],temp2-room[i]); 40 minn=min(temp-room[i],temp2-room[i]); 41 } 42 else if(op[j]=='/') 43 { 44 maxx=max(temp/room[i],temp2/room[i]); 45 minn=min(temp/room[i],temp2/room[i]); 46 } 47 else{ 48 maxx=max(temp*room[i],temp2*room[i]); 49 minn=min(temp*room[i],temp2*room[i]); 50 } 51 dpmax[i][j]=max(maxx,dpmax[i-1][j]); 52 dpmin[i][j]=min(minn,dpmin[i-1][j]); 53 if(i==j){ 54 dpmax[i][j]=maxx; 55 dpmin[i][j]=minn; 56 } 57 } 58 } 59 } 60 printf("%lld ",dpmax[n][m]); 61 } 62 63 }