• 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);
      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
    ", Ans); 
      for (int i = 1;i <= n; i++) if (f[i][i + n - 1] == Ans) printf("%d ",i);
      puts("");
      return 0;
    }
    
    
  • 相关阅读:
    一个JS的问题,请帮下忙!
    开始练习VS2003了
    SQL查询结果的合并问题
    几个微软的好东西!
    对谷歌输入发的一点疑虑
    Visual studio 2005 sdk 安装引起的后果
    Socket协议测试:TPS偏低,和响应时间计算出来的TPS不相符的问题
    数据库索引失效
    挡板模拟器桩模块驱动模块
    nmon 监控结果
  • 原文地址:https://www.cnblogs.com/Arielzz/p/15025798.html
Copyright © 2020-2023  润新知