• hdu3506 Monkey Party (区间dp+四边形不等式优化)


    题意:给n堆石子,每次合并相邻两堆,花费是这两堆的石子个数之和(1和n相邻),求全部合并,最小总花费

    若不要求相邻,可以贪心地合并最小的两堆。然而要求相邻就有反例

    为了方便,我们可以把n个数再复制一遍,放到第n个数后,就不用考虑环的问题了

    我们设f[i][j]为合并区间[i,j]所需要的最小花费,然后就可以得到

    f[i][j]=min{f[i][k]+f[k+1][j]+sum[i,j]} ,i<=k<=j,i<j;

    f[i][i]=0

    然后就可以用$O(n^3)$的复杂度递推啦。此题结束。

    然而n<=1000...

    四边形不等式:

    若f[i][j]=min{f[i][k]+f[k+1][j]+w[i][j]} ,i<=k<=j;

     s[i][j]为使f[i][j]取到最小值的k ,其中有(a<=b<=c<=d)

      1.w[b][c]<=w[a][d] (w满足区间包含单调性)

      2.w[a][c]+w[b][d]<=w[b][c]+w[a][d] (w满足四边形不等式)

     则f也满足四边形不等式(*)

     所以s[i][j-1]<=s[i][j]<=s[i+1][j] (**)

    *、**:太麻烦了不证了!

    于是就可以优化刚才的dp(sum显然满足以上两点),每次的k不是从i枚举到j,而是从s[i][j-1]枚举到s[i+1][j],这样,平摊下来,就可以在O(1)复杂度完成f[i][j]的计算

    然而我很沙雕的设f[i][j]表示长度为i,从j开始的区间了..虽然影响不大但是感觉写起来变得有点迷

    然后按照我的写法,n=1的时候是要特判的...

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<vector>
     5 #include<queue>
     6 #include<cmath>
     7 #define LL long long int
     8 #define inf 0x3f3f3f3f
     9 using namespace std;
    10 const int maxn=2010;
    11 
    12 LL rd(){
    13     LL x=0;char c=getchar();int neg=1;
    14     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
    15     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    16     return x*neg;
    17 }
    18 
    19 int N,num[maxn];
    20 int f[maxn][maxn][2],sum[maxn];
    21 
    22 int main(){
    23     int i,j,k;
    24     while(~scanf("%d",&N)){
    25         int ans=inf;
    26         for(i=1;i<=N;i++) num[i+N]=num[i]=rd();
    27         if(N==1){printf("0
    ");continue;}
    28         for(i=1;i<=2*N;i++) sum[i]=sum[i-1]+num[i],f[1][i][1]=i;
    29         for(i=2;i<=N;i++){
    30             for(j=1;j<2*N-i+1;j++){
    31                 f[i][j][0]=inf;
    32                 for(k=f[i-1][j][1];k<=f[i-1][j+1][1];k++){
    33                     int a=f[k-j+1][j][0]+f[i-k+j-1][k+1][0];
    34                     if(a<f[i][j][0]) f[i][j][0]=a,f[i][j][1]=k;
    35                 }f[i][j][0]+=sum[i+j-1]-sum[j-1];
    36             if(i==N) ans=min(ans,f[i][j][0]);
    37             }
    38         }printf("%d
    ",ans);
    39     }
    40     
    41     return 0;
    42 }
  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
  • 原文地址:https://www.cnblogs.com/Ressed/p/9409978.html
Copyright © 2020-2023  润新知