• 18.03.13 vijos1038添加括号


    背景

    给定一个正整数序列a(1),a(2),...,a(n),(1<=n<=20)
    不改变序列中每个元素在序列中的位置,把它们相加,并用括号记每次加法所得的和,称为中间和。

    例如:
    给出序列是4,1,2,3。

    第一种添括号方法:
    ((4+1)+(2+3))=((5)+(5))=(10)
    有三个中间和是5,5,10,它们之和为:5+5+10=20
    第二种添括号方法

    (4+((1+2)+3))=(4+((3)+3))=(4+(6))=(10)
    中间和是3,6,10,它们之和为19。

    描述

    现在要添上n-1对括号,加法运算依括号顺序进行,得到n-1个中间和,求出使中间和之和最小的添括号方法。如果有多组最优解,考虑将括号尽可能往前放。

    格式

    输入格式

    共两行。

    第一行,为整数n。(1<=n<=20)
    第二行,为a(1),a(2),...,a(n)这n个正整数,每个数字不超过100。

    输出格式

    输出3行。

    第一行,为添加括号的方法。

    第二行,为最终的中间和之和。

    第三行,为n-1个中间和,按照从左到右,从里到外的顺序输出。

    样例1

    样例输入1

    4
    4 1 2 3

    样例输出1

    (4+((1+2)+3))
    19
    3 6 10

    限制

    各个测试点1s

    来源

    MaoLaoda

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <math.h>
     4 #include <cstdio>
     5 #include <stdlib.h>
     6 #include <string.h>
     7 
     8 using namespace std;
     9 
    10 int num[30],f[30][30],h[30][30],sum[30][30],mid[100],step=0;//f[x][y]记录从x到y最小相加值,a=h[x][y]记录x到y最大值是由h[x][a]+h[a][y]得出的,mid记录中间数
    11 int inf=999999;
    12 
    13 int pri(int x,int y)
    14 {
    15     if(x==y)
    16     {
    17         printf("%d",num[x]);
    18         return num[x];
    19     }
    20     printf("(");
    21     int n1=pri(x,h[x][y]);
    22     printf("+");
    23     int n2=pri(h[x][y]+1,y);
    24     printf(")");
    25     mid[++step]=n1+n2;
    26     return mid[step];
    27 }
    28 
    29 int main()
    30 {
    31     int n;
    32     scanf("%d",&n);
    33     for(int i=1;i<=n;i++)
    34     {
    35         scanf("%d",&num[i]);
    36         sum[i][i]=num[i];
    37     }
    38     for(int i=1;i<=n;i++)
    39         for(int j=1;j<=n-i;j++)
    40             sum[i][i+j]=sum[i][i+j-1]+num[i+j];
    41     for(int i=1;i<=n-1;i++)
    42         for(int j=1;j<=n-i;j++)
    43         {
    44             f[j][j+i]=inf;
    45             for(int k=j;k<=j+i;k++)
    46                 if(f[j][k]+f[k+1][j+i]+sum[j][j+i]<=f[j][j+i])
    47                 {
    48                     f[j][j+i]=f[j][k]+f[k+1][j+i]+sum[j][j+i];
    49                     h[j][j+i]=k;
    50                 }
    51         }
    52     pri(1,n);
    53     printf("
    ");
    54     printf("%d
    ",f[1][n]);
    55     printf("%d",mid[1]);
    56     for(int i=2;i<=step;i++)
    57         printf(" %d",mid[i]);
    58     printf("
    ");
    59     return 0;
    60 }
    View Code

    不算很难的题,主要思想还是非常规矩的dp(状态很好想)

    但还是wa了两次,坑点在于要求括号提前

    但我其实不是没看见这个要求,但我没有get到题主“子串越长,括号越多”的潜规则

    现在想想稍微有道理一点了 不过括号提前这句话本身就有点……

    注定失败的战争,也要拼尽全力去打赢它; 就算输,也要输得足够漂亮。
  • 相关阅读:
    codevs1288 埃及分数
    codevs1792 分解质因数
    dp
    JAVA大数贪心
    求最长不重叠子串
    初识后缀数组
    dp
    两数相除,判断小数位是否有限位
    构造二分图匹配
    建立多个树状数组
  • 原文地址:https://www.cnblogs.com/yalphait/p/8563632.html
Copyright © 2020-2023  润新知