2018ACM—ICPC焦作网络预选赛B题 三维dp

版权声明:那个,最起码帮我加点人气吧,署个名总行吧 https://blog.csdn.net/qq_41670466/article/details/82763581

题意就是给你一个数组,再给你一个字符串,这个字符串保证只有+-*/这四个字符,现在你有一个初始值,当你在数组中选则一个值时,你就要用字符串头部的运算符进行运算,然后这个头部字符向后移一位,问当所有的字符都被使用后最大值是多少?

题目链接:https://nanti.jisuanke.com/t/31711

思路:从题意上理解可以得出:这道题类似于01背包,对于每个房间都有进或者不进的情况,只不过在此基础上又增加一个条件是运算符的不同,那么就可以使用一个二维dp,然鹅,考虑到可能会存在到某个房间时,sum为负值,然后此时的运算符为*或者/,然后这个房间的权值为负,那么此时最小的值就变成了正值,这一点要考虑到,那么dp就变成三维;

代码:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e3 + 10;
typedef long long ll;
int a[maxn];
ll dp[maxn][10][2];//dp[i][j][0]表示在第i个房间该第j个运算符时的值(o表示存储的最大值,1表示存储的此时最小值)
char s[maxn];

inline ll cal(ll sum, char b, int c)
{
	if (b == '+')
	{
		return sum + c;
	}
	else if (b == '-')
	{
		return sum - c;
	}
	else if (b == '*')
	{
		return sum * c;
	}
	else
	{
		return sum / c;
	}
}

int main()
{
	int t;
	scanf("%d", &t);
	while (t--)
	{
		int n, m, k;
		scanf("%d %d %d", &n, &m, &k);//这里之前用的是cin一直都是wa。。qaq以后再也不用cin输入了
		for (int i = 1; i <= n; i++)
		{
			scanf("%d", &a[i]);
		}
		scanf("%s", s + 1);
		for (int i = 0; i <= n; i++)
			dp[i][0][0] = dp[i][0][1] = k;
		for (int i = 1; i <= n; i++)
		{
			for (int j = 1; j <= min(i, m); j++)
			{
				ll a1 = cal(dp[i - 1][j - 1][0], s[j], a[i]);
				ll a2 = cal(dp[i - 1][j - 1][1], s[j], a[i]);
				dp[i][j][0] = max(a1, a2);
				dp[i][j][1] = min(a1, a2);
				if (i>j)
				{
					dp[i][j][0] = max(dp[i - 1][j][0], dp[i][j][0]);
					dp[i][j][1] = min(dp[i - 1][j][1], dp[i][j][1]);
				}
			}
		}
		printf("%lld\n", dp[n][m][0]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41670466/article/details/82763581