(区间DP) $O(n^3)$
这是一个标准的区间DP问题,这个题跟石子合并非常相似,只不过它是一个环形结构,所以形成一个2倍长度的链就可以很好的解决环形区间DP问题。
代码只是照着算法竞赛进阶指南的思路手撸了一遍,而且写的好像有点蠢,大家将就着看,如果有问题欢迎讨论。
C++ 代码
#include <bits/stdc++.h>
using namespace std;
int a[105];
char b[105];
int dpmax[105][105];
int dpmin[105][105];
int main()
{
int n;
int ret = 0;
scanf("%d",&n);
for(int i = 1; i <= 2*n; ++i) {
if(i % 2 == 1) {
cin>>b[(i/2)+1];
b[(i/2)+1+n] = b[(i/2)+1];
}
if(i % 2 == 0) {
cin>>a[i/2];
a[i/2+n] = a[i/2];
}
}
memset(dpmax,128,sizeof(dpmax));
memset(dpmin,0x3f3f,sizeof(dpmin));
for(int i = 1; i <= 2*n; ++i) {
dpmax[i][i] = a[i];
dpmin[i][i] = a[i];
}
for(int len = 1; len <= n; ++len)
for(int l = 1; l + len <= 2*n; ++l) {
int r = l + len;
for(int k = l; k < r; ++k) {
if(b[k+1] == 't') {
//cout<<"t"<<" ";
dpmax[l][r] = max(dpmax[l][r],dpmax[l][k] + dpmax[k+1][r]);
dpmin[l][r] = min(dpmin[l][r],dpmin[l][k] + dpmin[k+1][r]);
} else {
//cout<<"m"<<" ";
dpmax[l][r] = max(dpmax[l][r],dpmax[l][k]*dpmax[k+1][r]);
dpmax[l][r] = max(dpmax[l][r],dpmin[l][k]*dpmin[k+1][r]);
dpmin[l][r] = min(dpmin[l][r],dpmin[l][k]*dpmin[k+1][r]);
dpmin[l][r] = min(dpmin[l][r],dpmax[l][k]*dpmin[k+1][r]);
dpmin[l][r] = min(dpmin[l][r],dpmin[l][k]*dpmax[k+1][r]);
}
}
//cout<<l<<" "<<r<<" "<<dpmax[l][r]<<" "<<dpmin[l][r]<<" ";
}
for(int i = 1; i <= n; ++i) ret = max(ret,dpmax[i][i+n-1]);
printf("%d\n",ret);
//cout<<dpmax[2][5]<<" "<<a[2]<<" ";
for(int i = 1; i <= n; ++i)
if(dpmax[i][i+n-1] == ret) printf("%d ",i);
return 0;
}
为什么初始化小的是128啊
同问
int ret = -0x3f3f3f3f;
如果左边最小为-5最大为-1,右边最小为1最大为5,最大值不应该是左边最大乘右边最小吗
%%%
请问下为什么最大值只可能来自最大乘以最大或者最小乘以最小呢?
最小可能为两个负数
但最大也可能为负数,乘法应该考虑四种情况才对
不是最大最小都有四种情况吗?
是这样的
嗯,难道是测试数据不全面???
数据水ww
乘法只有2种情况(最大最大,最小最小),可以自己推导
如果左端最大是负数,右端最大是正数呢?这种情况应该是存在的吧>
应该讨论4种情况的,这道题只是数据水了否则是过不去的
明显错误的:对于取max与min均有反例(-1,-2),(2,1)。