• 【动态规划】Mathematical Curse


    【来源】: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 }
    View Code
  • 相关阅读:
    centos 编码问题 编码转换 cd到对应目录 执行 中文解压
    centos 编码问题 编码转换 cd到对应目录 执行 中文解压
    centos 编码问题 编码转换 cd到对应目录 执行 中文解压
    Android MVP 十分钟入门!
    Android MVP 十分钟入门!
    Android MVP 十分钟入门!
    Android MVP 十分钟入门!
    mysql备份及恢复
    mysql备份及恢复
    mysql备份及恢复
  • 原文地址:https://www.cnblogs.com/Osea/p/11297908.html
Copyright © 2020-2023  润新知