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

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

【Description】

A prince of the Science Continent was imprisoned in a castle because of his 
contempt for mathematics when he was young, and was entangled in some mathematical
curses. He studied hard until he reached adulthood and decided to use his knowledge 
to escape the castle.

There are NNN rooms from
the place where he was imprisoned to the exit of the castle. In the ithi^{th}ith room, there is a wizard who has a resentment value of a[i]a[i]a[i]. The prince has MMM curses, the jthj^{th}jth curse is f[j]f[j]f[j], and f[j]f[j]f[j] represents one of the four arithmetic operations, namely addition('+'), subtraction('-'), multiplication('*'), and
integer division('/'). The prince's initial resentment value is KKK. Entering a room and fighting with the wizard will eliminate a curse, but the prince's resentment value will become the result of the arithmetic operation f[j]f[j]f[j] with the wizard's resentment value. That is, if the prince eliminates the
jthj^{th}jth curse in the ithi^{th}ith room, then his resentment value will change from xxx to (x f[j] a[i]x\ f[j]\ a[i]x f[j] a[i]), for example, when x=1,a[i]=2,f[j]=x=1, a[i]=2, f[j]=x=1,a[i]=2,f[j]='+', then xxx will become 1+2=31+2=31+2=3. Before the prince escapes from the castle, he must eliminate all the curses. He must go from a[1]a[1]a[1] to a[N]a[N]a[N] in order and cannot turn back. He must also eliminate the f[1]f[1]f[1] to f[M]f[M]f[M] curses in order(It is guaranteed that N≥MN\ge MN≥M). What is the maximum resentment value that the prince may have when he leaves the castle?

【Input】

The first line contains an integer T(1≤T≤1000)T(1 \le T \le 1000)T(1≤T≤1000), which
is the number of test cases.

For each test case, the first line contains three non-zero integers: 
N(1≤N≤1000),M(1≤M≤5)N(1 \le N \le 1000), M(1 \le M \le 5)N(1≤N≤1000),M(1≤M≤5) and 
K(−1000≤K≤1000K(-1000 \le K \le 1000K(−1000≤K≤1000), the second line contains NNN 
non-zero integers: a[1],a[2],...,a[N](−1000≤a[i]≤1000)a[1], a[2], ..., a[N](-1000 
\le a[i] \le 1000)a[1],a[2],...,a[N](−1000≤a[i]≤1000), and the third line contains
MMM characters: f[1],f[2],...,f[M](f[j]=f[1], f[2], ..., f[M](f[j] 
=f[1],f[2],...,f[M](f[j]='+','-','*','/', with no spaces in between.

【Output】

 For each test case, output one line containing a single integer.

【Examples】

Sample Input

3
2 1 5
2 3
/
3 2 1
1 2 3
++
4 4 5
1 2 3 4
+-*/

Sample Output

2
6
3

【Problem Description】

有n個數,m個操作符,你的初始值為k。
按順序用當前值k對a[i]進行op[j]操作,操作結果為k=k op[j] a[i] (op[j]為四則運算的其中一種)
限制條件:
1、對於每個數a[i],只能從左到右選擇,無論前面的數使用過或未使用過,都不能回頭再選。
2、對於每個操作符op[j],只能從左到右選擇,並且每個操作符都必須使用且一次。
求最終的k的最大值

【Solution】

dp
定義dp陣列,
    dp1[i][j];//前i個數,經過前j個操作後所獲得的最大值
    dp2[i][j];//前i個數,經過前j個操作後所獲得的最小值
dp1[i][j]只能有三個狀態轉移過來
1、前i-1個數,經過前j個操作後的最大值
2、前i-1個數,經過前j-1個操作後的最大值再對a[i]執行op[j]操作後的值
2、前i-1個數,經過前j-1個操作後的最小值再對a[i]執行op[j]操作後的值
三個狀態中取最大的即可。
dp2[i][j]類似,不累述了。

【Code】

/*
 * @Author: Simon 
 * @Date: 2018-09-16 08:28:44 
 * @Last Modified by: Simon
 * @Last Modified time: 2018-09-16 09:22:42
 */
#include<bits/stdc++.h>
using namespace std;
typedef int Int;
#define int long long
#define INF 0x3f3f3f3f
#define maxn 1005
int a[maxn];
char op[7];
int dp1[maxn][7];//前i個數,經過前j個操作後所獲得的最大值
int dp2[maxn][7];//前i個數,經過前j個操作後所獲得的最小值
int cal(int a,char op,int k)//四種操作
{
    if(op=='+')
        return a+k;
    else if(op=='-')
        return k-a;
    else if(op=='*')
        return a*k;
    else if(op=='/')
        return k/a;
    return 0;
}
Int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    cin>>t;
    while(t--)
    {
        int n,m,k;
        cin>>n>>m>>k;
        for(int i=1;i<=n;i++) cin>>a[i];
        cin>>op+1;
        int len=strlen(op+1);
        memset(dp1,-INF,sizeof(dp1));
        memset(dp2,INF,sizeof(dp2));
        for(int i=0;i<=n;i++)
        {
            dp2[i][0] = k;
            dp1[i][0] = k;
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=min(len,i);j++)
            {
                dp1[i][j] = max(dp1[i - 1][j], cal(a[i], op[j], dp1[i - 1][j - 1]));//第1個轉移和第2個轉移中最大的
                dp1[i][j] = max(dp1[i][j], cal(a[i], op[j], dp2[i - 1][j - 1]));//三個狀態轉移中最大的
                dp2[i][j] = min(dp2[i - 1][j], cal(a[i], op[j], dp2[i - 1][j - 1]));
                dp2[i][j] = min(dp2[i][j],cal(a[i],op[j],dp1[i-1][j-1]));
            }
        }
        cout<<dp1[n][len]<<endl;
    }
    cin.get(),cin.get();
    return 0;
}