vijosP1038 添加括号
【思路】
区间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<<"\n"<<d[1][n]-(suma[n]-suma[0])<<"\n"; 48 for(int i=0;i<ans.size();i++) cout<<ans[i]<<" "; 49 return 0; 50 }