Loading

P4342 [IOI1998]Polygon

题面

\(IOI\) ?? 一道大水题

题面难以概括,还是去看原题吧

solution

环上 \(dp\) ,断环成链

然后做区间 \(dp\) 板子,枚举断点

这个题唯一的 \(tip\) 就是处理区间合并

因为区间合并有乘,所以有负负得正情况,所以还要维护一个区间最小值

对于合并要考虑一大堆情况,详细看这 题解 P4342 [IOI1998]Polygon

最后可以合并得到两个转移式 (\(g[i][j]\) 为区间最小值,\(f[i][j]\) 为区间最大值)

\(f[i][j]=max(f[i][j],max(f[i][k]×f[k+1][j],max(g[i][k]×g[k+1][j],max(f[i][k]×g[k+1][j],g[i][k]×f[k+1][j]))))\)

\(g[i][j]=min(g[i][j],min(f[i][k]×f[k+1][j],min(g[i][k]×g[k+1][j],min(f[i][k]×g[k+1][j],g[i][k]×f[k+1][j]))))\)

加的合并

\(f[i][j] = max(f[i][j], f[i][k] + f[k + 1][j]);\)

\(g[i][j] = min(g[i][j], g[i][k] + g[k + 1][j]);\)

注意代码输入格式!!

\(code\)

/*
work by:Ariel_
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int N = 150;
int read() {
  int x = 0, f = 1; char c = getchar();
  while(c < '0' || c > '9'){if (c == '-') f = -1;c = getchar();}
  while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
  return x * f;
}
int a[N], n, f[N][N], g[N][N];
char c[N]; 
int main(){
  scanf("%d\n", &n);
  for (int i = 1; i <= n; i++) {
  	scanf("%c %d", &c[i], &a[i]); getchar();
  	c[i + n] = c[i], a[i + n] = a[i];//断环成链 
  }
  memset(f, -0x3f3f3f3f, sizeof f), memset(g, 0x3f3f3f3f, sizeof g);
  for (int i = 1; i <= (n << 1); i++) f[i][i] = g[i][i] = a[i];
  for (int len = 1; len < n; len++)
  	for (int i = 1, j = i + len; j <= (n << 1); j++, i++) {
  		for (int k = i; k < j; k++) {
  		    if (c[k + 1] == 'x') {
  		    	f[i][j] = max(f[i][j], max(f[i][k] * f[k + 1][j], max(g[i][k] * g[k + 1][j], max(f[i][k] * g[k + 1][j], g[i][k] * f[k + 1][j]))));
  		    	g[i][j] = min(g[i][j], min(f[i][k] * f[k + 1][j], min(g[i][k] * g[k + 1][j], min(f[i][k] * g[k + 1][j], g[i][k] * f[k + 1][j])))); 
			  }	 
			if (c[k + 1] == 't') {
			   f[i][j] = max(f[i][j], f[i][k] + f[k + 1][j]);
			   g[i][j] = min(g[i][j], g[i][k] + g[k + 1][j]);
			}  
		  }
	  }
  int Ans = -0x3f3f3f3f;
  for (int i = 1; i <= n; i++) Ans = max(Ans, f[i][i + n - 1]);
  printf("%d\n", Ans); 
  for (int i = 1;i <= n; i++) if (f[i][i + n - 1] == Ans) printf("%d ",i);
  puts("");
  return 0;
}

posted @ 2021-07-18 08:04  Dita  阅读(36)  评论(0编辑  收藏  举报