地址:https://nanti.jisuanke.com/t/31711
这个dp是个简单dp,赛场上思路是对的,负负得正,说明当前最大值可以来自前面的最大值或者最小值。。。。这个没想到,还是菜。。。。。。
dp[i][j]表示选到了第i个数时用了j个运算符,观察发现,一个数只能由他前一个状态的最大值或最小值转移过来(因为乘上一个负数会使最小的数变最大),所以我们同时维护最大最小。
然后转移就行了
转移方程:dp[i][j] = max(dp[i - 1][j],dp[i - 1][j - 1] 操作数 a[i]);
要注意i - 1 >= y 和i == y
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
LL MAX[1005][8];
LL MIN[1005][8];
LL a[1005];
char f[15];
LL jisuan(LL k,char s,LL val)
{
LL x;
switch(s)
{
case '+':x = k + val;break;
case '-':x = k - val;break;
case '*':x = k * val;break;
case '/':x = k / val;break;
}
return x;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m,k;
scanf("%d %d %d",&n,&m,&k);
for(int i = 1;i <= n;++i)
{
scanf("%lld",&a[i]);
}
scanf("%s",f);
memset(MAX,0,sizeof(MAX));
memset(MIN,0,sizeof(MIN));
for(int i = 0;i <= n;++i)
{
MIN[i][0] = k;
MAX[i][0] = k;
}
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= m;++j)
{
if(i >= j){
LL x = jisuan(MAX[i - 1][j - 1],f[j - 1],a[i]);
LL y = jisuan(MIN[i - 1][j - 1],f[j - 1],a[i]);
LL maxx = max(x,y);
LL minn = min(x,y);
if(i == j){
MAX[i][j] = maxx;
MIN[i][j] = minn;
continue;
}
MAX[i][j] = max(MAX[i - 1][j],maxx);
MIN[i][j] = min(MIN[i - 1][j],minn);
}
}
}
LL MAXX = -inf;
for(int i = m;i <= n;++i)
MAXX = max(MAXX,MAX[i][m]);
printf("%lld\n",MAXX);
}
return 0;
}