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("\n");
54     printf("%d\n",f[1][n]);
55     printf("%d",mid[1]);
56     for(int i=2;i<=step;i++)
57         printf(" %d",mid[i]);
58     printf("\n");
59     return 0;
60 }
View Code

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

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

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

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

转载于:https://www.cnblogs.com/yalphait/p/8563632.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值