【dp】ACM-ICPC 2018 焦作賽區網路預賽 - B - Mathematical Curse
阿新 • • 發佈:2018-11-10
題目連結<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); } }