zoukankan      html  css  js  c++  java
  • NIOP1995 石子合并(区间DP)

    状态转移方程在代码中标出

    本题注意是圆形,所以之前要预先处理一下s数组。处理之后总长度为2*n-1.第一个合并的起点有n个,所以总的方案数是n

    注释在代码中标出

    http://www.rqnoj.cn/problem/490

    石子合并问题推荐几篇很好的文章

    http://blog.csdn.net/acdreamers/article/details/18039073

    http://blog.csdn.net/bnmjmz/article/details/41308919

    注意四边形不等式优化,可以把n^3优化到n^2

     1 //#pragma comment(linker, "/STACK:167772160")//手动扩栈~~~~hdu 用c++交
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<iostream>
     6 #include<queue>
     7 #include<stack>
     8 #include<cmath>
     9 #include<set>
    10 #include<algorithm>
    11 #include<vector>
    12 // #include<malloc.h>
    13 using namespace std;
    14 #define clc(a,b) memset(a,b,sizeof(a))
    15 #define LL long long
    16 const int Inf = 0x3f3f3f3f;
    17 const double eps = 1e-5;
    18 const double pi = acos(-1);
    19 // inline int r(){
    20 //     int x=0,f=1;char ch=getchar();
    21 //     while(ch>'9'||ch<'0'){if(ch=='-') f=-1;ch=getchar();}
    22 //     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    23 //     return x*f;
    24 // }
    25 const int Times = 10;
    26 const int N = 5500;
    27 int s[210],d[210][210],p[210][210],a[210];//d/p表示i到j的最小/大花费
    28 int main(){
    29     int n;
    30     int m;
    31     s[0]=0;
    32     while(~scanf("%d",&n)){
    33         clc(d,0);
    34         clc(p,0);
    35         for(int i=1;i<=n;i++){
    36             scanf("%d",&a[i]);
    37             s[i]=s[i-1]+a[i];
    38         }
    39         for(int i=1;i<n;i++){
    40             s[i+n]=s[n+i-1]+a[i];
    41         }
    42         m=n,n=n*2-1;
    43         int j,tem1,tem2;
    44         for(int r=2;r<=n;r++){//枚举i到j的长度
    45             for(int i=1;i<=n-r+1;i++){//i起始坐标,j表示当前枚举的终点坐标
    46                  j=i+r-1,tem1=Inf,tem2=0;
    47                  for(int k=i;k<j;k++){
    48                     tem1=min(tem1,d[i][k]+d[k+1][j]+s[j]-s[i-1]);
    49                     tem2=max(tem2,p[i][k]+p[k+1][j]+s[j]-s[i-1]);
    50                  }
    51                  d[i][j]=tem1;
    52                  p[i][j]=tem2;
    53             }
    54         }
    55         tem1=Inf,tem2=0;
    56         for(int i=1;i<=m;i++){//合并长度从1到m
    57             if(tem1>d[i][m+i-1]) tem1=d[i][m+i-1];
    58             if(tem2<p[i][m+i-1]) tem2=p[i][m+i-1];
    59         }
    60         if(n==1) tem1=tem2=a[1];
    61         printf("%d
    %d
    ",tem1,tem2);
    62     }
    63     return 0;
    64 }
    View Code
  • 相关阅读:
    用Python作GIS:择菜篇
    【嵌入式开发技术之串口】Linux下串口主机程序
    1033,2052 是什么意思?
    Telnet协议详解
    生活情景英语:英语国家生存英语精选
    windows下搭建iphone开发环境
    开公司的流程
    解决某物流企业二维码打印问题
    数字黑洞
    InnoSetup 打包代码 检测.netFramework
  • 原文地址:https://www.cnblogs.com/ITUPC/p/5466535.html
Copyright © 2011-2022 走看看