【来源】:2018年焦作网络赛B
【题意】:
有n个数字,有m个符号运算。通过不回头(即选取m个数有顺序可言),消除巫术的,并达到最大的价值。
其实意思就是在数组里选取一段子序列,然后进行m次加减乘除的运算。最后使答案最大化。
【思路】:
考虑DP,我们考虑加减时只需要考虑最大值即可,但是乘除两个运算的加入就会使这个题目变得复杂了。
然后我们需要的记录最大值和最小值,因为每一个值可能是从最大值转移过来,也有可能最小值转移过来的。
所以需要同时记录。
【注意】:
1、记得初始化(多组数据)
2、如果直接转移会耗费O(n^2),其实我们只是关心前i个里面获取的最大值,所以我们需要压缩,从前一个数字的暂存值进行更新。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N = 1e4+10; 5 const int M = 6; 6 const ll inf = 0x7fffffffffffffff; 7 ll dp[N][M][2]; //0_ 最小值 ,1 最大值 8 ll a[N]; 9 int main(){ 10 int T; 11 int n,m,k; 12 char opt[M] ; 13 for( scanf("%d",&T) ; T ;T-- ){ 14 scanf("%d%d%d",&n,&m,&k); 15 for(int i=1;i<=n;i++) scanf("%lld",&a[i]); 16 scanf("%s",opt+1); 17 18 for(int i=0;i<=n;i++){ 19 for(int j=0;j<=m;j++){ 20 dp[i][j][0] = inf ; 21 dp[i][j][1] = -inf ; 22 } 23 } 24 25 for(int i=0;i<=n;i++){ 26 dp[i][0][0] = dp[i][0][1] = k; 27 } 28 29 30 for(int j=1;j<=m;j++){ 31 for(int i=1;i<=n;i++){ 32 if( i > j ){ 33 dp[i][j][0] = dp[i-1][j][0]; 34 dp[i][j][1] = dp[i-1][j][1]; 35 } 36 37 if( opt[j] =='+'){ 38 dp[i][j][0] = min( dp[i][j][0] , dp[i-1][j-1][0] + a[i] ); 39 dp[i][j][0] = min( dp[i][j][0] , dp[i-1][j-1][1] + a[i] ); 40 41 dp[i][j][1] = max( dp[i][j][1] , dp[i-1][j-1][0] + a[i] ); 42 dp[i][j][1] = max( dp[i][j][1] , dp[i-1][j-1][1] + a[i] ); 43 }else if( opt[j] == '-'){ 44 dp[i][j][0] = min( dp[i][j][0] , dp[i-1][j-1][0] - a[i] ); 45 dp[i][j][0] = min( dp[i][j][0] , dp[i-1][j-1][1] - a[i] ); 46 47 dp[i][j][1] = max( dp[i][j][1] , dp[i-1][j-1][0] - a[i] ); 48 dp[i][j][1] = max( dp[i][j][1] , dp[i-1][j-1][1] - a[i] ); 49 }else if( opt[j] == '*' ){ 50 dp[i][j][0] = min( dp[i][j][0] , dp[i-1][j-1][0] * a[i] ); 51 dp[i][j][0] = min( dp[i][j][0] , dp[i-1][j-1][1] * a[i] ); 52 53 dp[i][j][1] = max( dp[i][j][1] , dp[i-1][j-1][0] * a[i] ); 54 dp[i][j][1] = max( dp[i][j][1] , dp[i-1][j-1][1] * a[i] ); 55 }else{ 56 dp[i][j][0] = min( dp[i][j][0] , dp[i-1][j-1][0] / a[i] ); 57 dp[i][j][0] = min( dp[i][j][0] , dp[i-1][j-1][1] / a[i] ); 58 59 dp[i][j][1] = max( dp[i][j][1] , dp[i-1][j-1][0] / a[i] ); 60 dp[i][j][1] = max( dp[i][j][1] , dp[i-1][j-1][1] / a[i] ); 61 } 62 } 63 } 64 65 printf("%lld ",dp[n][m][1]); 66 } 67 return 0 ; 68 }