石子合并
这道题是不可以用贪心的:因为每次要求合并相邻的两堆,不能保证每次合并的都是最多的,或是最少的
有一道题是链式的:石子归并
加上环怎么办?
断环为链:将长度为n的链复制一份接在后面,环的情况就是长度为2n的链中任意连续的长度为n的链。
注意平行四边形只能用于min,这道题要求的max是不能用平行四边形优化的
朴素AC_Code:
1 #include <bits/stdc++.h> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <cmath> 6 #include <queue> 7 #include <stack> 8 #include <vector> 9 #include <set> 10 #include <map> 11 #include <algorithm> 12 using namespace std; 13 typedef long long ll; 14 const int maxn=205; 15 const ll mod=1e9+7; 16 const ll INF=1e18; 17 const double eps = 1e-9; 18 19 int n,x; 20 int sum[maxn]; 21 int dp1[maxn][maxn];///合并第i堆到第j堆石子的最小代价 22 int dp2[maxn][maxn];///合并第i堆到第j堆石子的最大代价 23 int w[maxn]; 24 int main() 25 { 26 scanf("%d",&n); 27 sum[0]=0; 28 memset(dp1,0x3f,sizeof(dp1)); 29 for(int i=1;i<=n;i++){ 30 scanf("%d",&w[i]); 31 dp1[i][i]=0; 32 dp2[i][i]=0; 33 dp1[i+n][i+n]=0; 34 dp2[i+n][i+n]=0; 35 sum[i]=sum[i-1]+w[i]; 36 } 37 for(int i=1;i<=n;i++){ 38 sum[n+i]=w[i]+sum[i+n-1]; 39 } 40 for(int len=2;len<=n;len++){ 41 for(int i=1;i<=2*n-1;i++){ 42 int j=i+len-1; 43 if( j>2*n-1 ) break; 44 for(int k=i;k<j;k++){ 45 dp1[i][j]=min(dp1[i][j],dp1[i][k]+dp1[k+1][j]+(sum[j]-sum[i-1])); 46 dp2[i][j]=max(dp2[i][j],dp2[i][k]+dp2[k+1][j]+(sum[j]-sum[i-1])); 47 } 48 } 49 } 50 int ans1=0x3f3f3f3f; 51 int ans2=0; 52 for(int i=1;i<=n;i++){///形成了环任何一位都可以当作开头 53 ans1=min(ans1,dp1[i][i+n-1]); 54 } 55 for(int i=1;i<=n;i++){ 56 ans2=max(ans2,dp2[i][i+n-1]); 57 } 58 printf("%d\n%d\n",ans1,ans2); 59 return 0; 60 }