石子合并

 

 这道题是不可以用贪心的:因为每次要求合并相邻的两堆,不能保证每次合并的都是最多的,或是最少的

有一道题是链式的:石子归并

加上环怎么办?

断环为链:将长度为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 }

 

posted @ 2020-02-02 11:04  swsyya  阅读(133)  评论(0编辑  收藏  举报

回到顶部