题目描述:
思路:
因为n并不大,所以很容易想到枚举一下第一步去掉的边。
然后展开应为符号和点交杂的一条线,如果符号只有‘+’,那么用区间dp求其最优解应该很简单啦,同样小区间推大区间,dp[i][j] = dp[i][k-1]+dp[k][j].现在考虑‘’,不能向‘+’一样简单的相乘就可以,因为如果两边是负数,那么两边最小才能使值最大,那么我们在过程最小值和最大值都需要记忆化,在‘’时,列举四种:(minn*minn , maxn*minn , maxn*maxn , minn*maxn)取最优即可。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 110;
int minn[N][N],maxn[N][N];
int record[N];
char ver[N];
int a[N];
int main()
{
int n;
scanf("%d",&n);
for(int i = 1; i <= n; i++)
{
getchar();
scanf("%c %d",&ver[i],&a[i]);
ver[i+n] = ver[i];
a[i+n] = a[i];
}
int ans = -INF;
for(int v = 1; v <= n; v++)
{
int x = v, y = v+n-1;
memset(minn,0,sizeof(minn));
memset(maxn,0,sizeof(maxn));
for(int i = x; i <= y; i++)
minn[i][i] = maxn[i][i] = a[i];
for(int len = 1; len < n; len++)
{
for(int i = x; i+len <= y; i++)
{
int l = i, r = i+len;
maxn[l][r] = -INF;
minn[l][r] = INF;
for(int k = l+1; k <= r; k++)
{
if(ver[k] == 't')
{
maxn[l][r] = max(maxn[l][r],maxn[l][k-1]+maxn[k][r]);
minn[l][r] = min(minn[l][r],minn[l][k-1]+minn[k][r]);
}
else
{
maxn[l][r] = max(maxn[l][r],maxn[l][k-1]*maxn[k][r]);
minn[l][r] = min(minn[l][r],maxn[l][k-1]*maxn[k][r]);
maxn[l][r] = max(maxn[l][r],maxn[l][k-1]*minn[k][r]);
minn[l][r] = min(minn[l][r],maxn[l][k-1]*minn[k][r]);
maxn[l][r] = max(maxn[l][r],minn[l][k-1]*minn[k][r]);
minn[l][r] = min(minn[l][r],minn[l][k-1]*minn[k][r]);
maxn[l][r] = max(maxn[l][r],minn[l][k-1]*maxn[k][r]);
minn[l][r] = min(minn[l][r],minn[l][k-1]*maxn[k][r]);
}
}
}
}
//printf("%d\n",maxn[x][y]);
record[v] = maxn[x][y];
if(maxn[x][y] > ans)
ans = maxn[x][y];
}
printf("%d\n",ans);
int flag = 0;
for(int v = 1; v <= n; v++)
{
if(record[v] == ans)
{
if(flag == 0)
printf("%d",v);
else
printf(" %d",v);
flag = 1;
}
}
puts("");
return 0;
}
本文介绍了一种使用区间动态规划解决特定符号运算问题的方法。针对输入的符号串和数值,通过枚举移除边的方式,结合区间DP算法,求解在不同运算符作用下能够达到的最大值。代码实现中详细展示了如何进行状态转移,并记录最优解。
1757

被折叠的 条评论
为什么被折叠?



