POJ1179——Polygon(区间dp)

传送门

区间dp不用说了吧

主要在于要考虑好几种情况

f[i][j]f[i][j]表示区间iji-j的最大值

考虑如果是加

就直接加就是了

但如果是乘

却不一定了

考虑到有可能最大值会由两个最小的负数相乘而来的

所以我们还要维护一个区间最小值

而区间最小值的乘有可能由最小值乘最小值,最大值乘最小值(正*负)而来

所以每次合并区间都要枚举所以可能

#include<algorithm>
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
inline int read(){
	char ch=getchar();
	int res=0,f=1;
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
	return res*f;
}
int f[105][105][2],a[105],op[105],n;//0是最小值,1是最大值
char ch;
int main(){
	n=read();
	for(int i=1;i<=n;i++){
		cin>>ch;
		if(ch=='t'){
			op[i+n-1]=op[i-1]=1;
		}
		else op[i+n-1]=op[i-1]=2;
		a[i]=a[i+n]=read();
	}
	for(int i=1;i<=2*n;i++){
		f[i][i][0]=f[i][i][1]=a[i];
	}
	for(int len=1;len<n;len++){
		for(int l=1;l+len<=2*n;l++){
			int r=(l+len);
			int g1=-1e4,g2=1e4;
 			for(int k=l;k<r;k++){
				if(op[k]==2){
					g1=max(max(f[l][k][1]*f[k+1][r][1],f[l][k][0]*f[k+1][r][0]),g1);
					g2=min(min(g2,f[l][k][0]*f[k+1][r][0]),min(f[l][k][1]*f[k+1][r][0],f[l][k][0]*f[k+1][r][1]));
				}
				else{
					g1=max(g1,f[l][k][1]+f[k+1][r][1]);
					g2=min(g2,f[l][k][0]+f[k+1][r][0]);
				}
			}
			f[l][r][0]=g2;
			f[l][r][1]=g1;
		}
	}
	int maxn=-1e7,k=0;
	for(int i=1;i<=n;i++){
		if(f[i][i+n-1][1]>maxn){
			k=i,maxn=f[i][i+n-1][1];
		}
	}
	cout<<maxn<<'\n';
	for(int i=1;i<=n;i++){
		if(f[i][i+n-1][1]==maxn){
			cout<<i<<" ";
		}
	}
}
posted @ 2018-11-02 20:06  Stargazer_cykoi  阅读(92)  评论(0编辑  收藏  举报