题意:给你n个数,m个运算符,初始值为k

让你选择m个数进行计算,输出计算后的最大数,需要注意的是,计算选择必须按照顺序,不可乱序选择

本题是一个很显然的dp问题,枚举数和运算符进行计算即可。

需要注意的点1:因为计算中可能存在负数,所以我们需要同时维护一个最大值和最小值,当当前值为负数,且之后计算中存在负数时,我们就可以负负得正得到正数。

需要注意的点2:注意当我们枚举数和运算符时,当枚举的数的数量不大于运算符的数量

 

代码如下:

#include<cstdio>
#include<algorithm>

using namespace std;

typedef long long ll;

const int N = 1010, M = 10;
int n, m;
ll k;
ll a[N];
ll dpmax[N][M], dpmin[N][M];
char f[M];

int main()
{
	int T;
	scanf("%d", &T);
	
	while(T--){
		scanf("%d%d%lld", &n, &m, &k);
		
		for(int i = 1; i <= n; i++)
			scanf("%lld", &a[i]);
		
		scanf("%s", f + 1);
		
		dpmax[0][0] = dpmin[0][0] = k;
		for(int i = 1; i <= n; i++){ 
			dpmax[i][0] = dpmin[i][0] = k;
			
			/*限制运算符的数量不得超过数的数量*/
			int jmax = min(m, i);
			for(int j = 1; j <= jmax; j++){
				dpmax[i][j] = dpmax[i - 1][j];
				dpmin[i][j] = dpmin[i - 1][j];
				
				ll tmax = dpmax[i - 1][j - 1];
				ll tmin = dpmin[i - 1][j - 1];
				
				switch(f[j]){
					case '+' : tmax += a[i]; tmin += a[i]; break;
					case '-' : tmax -= a[i]; tmin -= a[i]; break;
					case '*' : tmax *= a[i]; tmin *= a[i]; break;
					case '/' : tmax /= a[i]; tmin /= a[i]; break;	
				}
				if(tmax < tmin){
					ll temp = tmax;
					tmax = tmin;
					tmin = temp;
				}
				
				/*判断下临界问题,即当i==j的时候,必须选择是第i个数选择了第j个运算符进行计算*/
				if(i == j){
					dpmax[i][j] = tmax;
					dpmin[i][j] = tmin;
				}
				else{ 
					dpmax[i][j] = max(dpmax[i][j], tmax);
					dpmin[i][j] = min(dpmin[i][j], tmin);
				} 
			}
		}
		printf("%lld\n", dpmax[n][m]);
	}
	return 0;
}