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

ACM-ICPC 2018 焦作賽區網路預賽 B. Mathematical Curse(dp)

樣例輸入 
3
2 1 5
2 3
/
3 2 1
1 2 3
++
4 4 5
1 2 3 4
+-*/
樣例輸出 
2
6
3

題意: n個數字,m個運算子(+-*/),從n個數字中選擇m個數字,按原陣列順序與k進行運算,使得最後結果最大

思路:對dp一竅不通,隊友過的,事後理解了再補上做法,先放隊友的程式碼dp[i][j]表示第i個數字,j個操作符下的結果

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
ll calc(ll x,char op,ll y)
{
    switch(op){
        case '+':
            return x+y;
        case '-':
            return x-y;
        case '*':
            return x*y;
        case '/':
            return x/y;
    }
}
int T,n,m;
ll k;
ll a[1005],dp[1005][6],pd[1005][6];
char f[15];
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        memset(dp,0x80,sizeof(dp));
        memset(pd,0x3f,sizeof(pd));
        scanf("%d %d %lld",&n,&m,&k);
        for(int i=1;i<=n;i++)
            scanf("%lld",a+i);
        scanf("%s",f+1);

        for(int i=0;i<=n;i++)
            pd[i][0]=dp[i][0]=k;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                if(i<=m&&j>i)break;
                dp[i][j]=max(dp[i-1][j],calc(dp[i-1][j-1],f[j],a[i]));
                pd[i][j]=min(pd[i-1][j],calc(pd[i-1][j-1],f[j],a[i]));
                dp[i][j]=max(dp[i][j],calc(pd[i-1][j-1],f[j],a[i]));
                pd[i][j]=min(pd[i][j],calc(dp[i-1][j-1],f[j],a[i]));
            }

        printf("%lld\n",dp[n][m]);
    }
    return 0;
}