1. 程式人生 > >【dp】ACM-ICPC 2018 焦作賽區網路預賽 - B - Mathematical Curse

【dp】ACM-ICPC 2018 焦作賽區網路預賽 - B - Mathematical Curse

題目連結<https://nanti.jisuanke.com/t/31711>


題意:

有n個數,m個加減乘除的運算子。按順序取出m個數,進行對應的運算子操作。給你一個初始值,問能構成的最大結果是多少。


題解:

考慮只有加減這兩種運算子的情況,那麼可以想到一個n*m的做法。

設一個dp[i][j]陣列表示對第i個數字做操作,且已經做了j次的操作。

dp[i][j]一定是從dp[k][j-1](k<i)中最大的那個轉移過來的,所以只需維護一個最大值即可。

而多了乘除兩個操作,那麼就可能出現比較小的負數,再乘除一個負數後變得很大,考慮到這種情況,只需要再維護一個最小值即可。


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
ll dp[2000][10][2];
ll a[2000];
char s[10];
ll t,n,m,k;
int main(){
    scanf("%lld",&t);
    while(t--){
        scanf("%lld%lld%lld",&n,&m,&k);
        for(ll i=1;i<=n;i++) scanf("%lld",&a[i]),dp[i][0][0]=dp[i][0][1]=k;
        dp[0][0][0]=dp[0][0][1]=k;
        scanf("%s",s+1);
        ll maxn,minn;
        for(ll j=1;j<=m;j++){
            maxn=dp[j-1][j-1][1];
            minn=dp[j-1][j-1][0];
            for(ll i=1;i<=n;i++){
                if(i>=j){
                    maxn=max(maxn,dp[i-1][j-1][1]);
                    minn=min(minn,dp[i-1][j-1][0]);
                    if(s[j]=='+'){
                        dp[i][j][1]=maxn+a[i];
                        dp[i][j][0]=minn+a[i];
                    }
                    else if(s[j]=='-'){
                        dp[i][j][1]=maxn-a[i];
                        dp[i][j][0]=minn-a[i];
                    }
                    else if(s[j]=='*'){
                        dp[i][j][1]=max(minn*a[i],maxn*a[i]);
                        dp[i][j][0]=min(minn*a[i],maxn*a[i]);
                    }
                    else if(s[j]=='/'){
                        if(a[i]==0){
                            dp[i][j][1]=dp[i-1][j][1];
                            dp[i][j][0]=dp[i-1][j][0];
                        }
                        else{
                            dp[i][j][1]=max(minn/a[i],maxn/a[i]);
                            dp[i][j][0]=min(minn/a[i],maxn/a[i]);
                        }
                    }
                }
            }
        }
        ll ans=dp[m][m][1];
        for(ll i=m;i<=n;i++){
            ans=max(ans,dp[i][m][1]);
        }
        printf("%lld\n",ans);
    }
}