题目网址:https://www.luogu.com.cn/problem/P1880
题意是:给定一个序列,最小规则是相邻两个值的合并,开销是他们的和,将整个序列合并成一个值的情况下,求解该值的最小值和最大值。
代码如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef unsigned int ui; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 #define pf printf 7 #define mem(a,b) memset(a,b,sizeof(a)) 8 #define prime1 1e9+7 9 #define prime2 1e9+9 10 #define scand(x) scanf("%llf",&x) 11 #define f(i,a,b) for(int i=a;i<=b;i++) 12 #define scan(a) scanf("%d",&a) 13 #define dbg(args) cout<<#args<<":"<<args<<endl; 14 #define pb(i) push_back(i) 15 #define ppb(x) pop_back(x) 16 #define inf 0x3f3f3f3f 17 #define maxn 1005 18 int n,m,t,max_ans,min_ans=inf,a[maxn],dp1[maxn][maxn],dp2[maxn][maxn],b[maxn]; 19 int dfs1(int l,int r)//max 20 { 21 if(l==r)return 0; 22 if(dp1[l][r])return dp1[l][r]; 23 if(r==l+1)return a[l]+a[l+1]; 24 int res=0; 25 f(i,l,r-1) 26 { 27 28 res=max(res,dfs1(l,i)+dfs1(i+1,r)+b[r]-b[l-1]); 29 } 30 return dp1[l][r]=res; 31 } 32 int dfs2(int l,int r)//min 33 { 34 if(l==r)return 0; 35 if(dp2[l][r]!=inf)return dp2[l][r]; 36 if(r==l+1)return a[l]+a[l+1]; 37 int res=inf; 38 f(i,l,r-1) 39 { 40 res=min(res,dfs2(l,i)+dfs2(i+1,r)+b[r]-b[l-1]); 41 } 42 return dp2[l][r]=res; 43 } 44 int main() 45 { 46 //freopen("input.txt","r",stdin); 47 //freopen("output.txt","w",stdout); 48 std::ios::sync_with_stdio(false); 49 scan(n); 50 mem(dp1,0); 51 mem(dp2,inf); 52 max_ans=-inf; 53 min_ans=inf; 54 f(i,1,n) 55 { 56 scan(a[i]); 57 a[i+n]=a[i]; 58 } 59 f(i,1,2*n) 60 { 61 b[i]=b[i-1]+a[i]; 62 } 63 f(i,1,n) 64 { 65 max_ans=max(max_ans,dfs1(i,n+i-1)); 66 min_ans=min(min_ans,dfs2(i,n+i-1)); 67 } 68 pf("%d %d",min_ans,max_ans); 69 }