vijosP1038 添加括号

vijosP1038 添加括号

链接:https://vijos.org/p/1038

【思路】

   区间DP。

   本题的关键在于如何输出解。对于求和表达式而言可以用一个p[][]记录决策然后递归输出,对于部分和而言可以在递归的同时用一个ans保存。

   本题需要注意的就是从左到右由里到外的输出顺序,就是如果部分和相等则记录k大的一个决策。

【代码】

 1 #include<iostream>
 2 #include<cstring>
 3 #include<vector>
 4 using namespace std;
 5 
 6 const int maxn = 100+10;
 7 
 8 int a[maxn],d[maxn][maxn];
 9 int suma[maxn],p[maxn][maxn];
10 vector<int> ans;
11 int n;
12 
13 void print(int i,int j) {
14     if(i==j) cout<<a[i];
15     else {
16         cout<<'(';
17         print(i,p[i][j]);
18         cout<<'+';
19         print(p[i][j]+1,j);
20         cout<<')';
21         ans.push_back(suma[j]-suma[i-1]);
22     }
23 }
24 
25 int main() {
26     ios::sync_with_stdio(false);
27     memset(d,60,sizeof(d));
28     cin>>n;
29     for(int i=1;i<=n;i++) cin>>a[i] ;
30     suma[0]=0;
31     for(int i=1;i<=n;i++) suma[i] += suma[i-1]+a[i] , d[i][i]=a[i]; 
32     
33     for(int l=1;l<=n;l++)
34        for(int i=1;i+l<=n;i++)
35        {
36               int j=i+l;
37            for(int k=i;k<j;k++)
38            {
39               int tmp=d[i][k]+d[k+1][j]+suma[j]-suma[i-1];
40               if(d[i][j]>=tmp) {
41                     d[i][j]=tmp;
42                     p[i][j]=k;
43               }
44            }
45        }
46     print(1,n);
47     cout<<"
"<<d[1][n]-(suma[n]-suma[0])<<"
";
48     for(int i=0;i<ans.size();i++) cout<<ans[i]<<" ";
49     return 0;
50 }
原文地址:https://www.cnblogs.com/lidaxin/p/4900940.html