zoukankan      html  css  js  c++  java
  • zjnu1181 石子合并【基础算法・动态规划】——高级

    Description

    在操场上沿一直线排列着 
    n堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的两堆石子合并成新的一堆, 
    并将新的一堆石子数记为该次合并的得分。允许在第一次合并前对调一次相邻两堆石子的次序。 

    计算在上述条件下将n堆石子合并成一堆的最小得分。 

    Input

    输入数据共有二行,其中,第1行是石子堆数n≤100; 

    第2行是顺序排列的各堆石子数(≤20),每两个数之间用空格分隔。 

    Output

    输出合并的最小得分。

    Sample Input

    3 2 5 1

    Sample Output

    11

    第一道区间dp,这题设一个数组dp[i][j]表示从i取到j的最小得分。

    状态转移方程:用len表示所选数字的个数,dp[i][i+len-1]=min(dp[i][i+len-1],dp[i][k]+dp[k+1][i+len-1]+sum[i+len-1]-sum[i-1]);这里注意所有的dp[i][i]为0,因为只有一个数的时候不用合并,所以是0。因为题目允许第一次开始取的时候相邻数字能搞交换,所以外面加个循环,同时每次的sum[]都要重新初始化。另外,这题用四边形优化会大大加快速度。

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<string>
    #include<algorithm>
    using namespace std;
    #define inf 99999999
    #define ll long long
    int sum[200],a[200];
    int dp[200][200];
    int main()
    {
        int n,m,i,j,c,len,k,t;
        int minx;
        while(scanf("%d",&n)!=EOF)
        {
            sum[0]=0;
            for(i=1;i<=n;i++){
                scanf("%d",&a[i]);
                sum[i]=sum[i-1]+a[i];
                dp[i][i]=0;
            }
    
            minx=inf;
            for(t=1;t<=n-1;t++){
                sum[t]=sum[t]-a[t]+a[t+1];
                for(len=2;len<=n;len++){
                    for(i=1;i<=n-len+1;i++){
                        dp[i][i+len-1 ]=inf;
                        for(k=i;k<=i+len-2;k++){
                            dp[i][i+len-1]=min(dp[i][i+len-1],dp[i][k]+dp[k+1][i+len-1]+sum[i+len-1]-sum[i-1]);
                        }
                    }
                }
                sum[t]=sum[t]+a[t]-a[t+1];
                minx=min(minx,dp[1][n]);
            }
    
    
            printf("%d
    ",minx);
    
        }
        return 0;
    }
    

    四边形优化:
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<string>
    #include<algorithm>
    using namespace std;
    #define inf 99999999
    #define ll long long
    int sum[200],a[200],s[200][200];/*s[i][j]函数表示区间[i,j]从k点分开是最优的*/
    int dp[200][200];
    int main()
    {
        int n,m,i,j,c,len,k,t;
        int minx;
        while(scanf("%d",&n)!=EOF)
        {
            sum[0]=0;
            for(i=1;i<=n;i++){
                scanf("%d",&a[i]);
                s[i][i]=i;
                sum[i]=sum[i-1]+a[i];
                dp[i][i]=0;
            }
    
            minx=inf;
            for(t=1;t<=n-1;t++){
                sum[t]=sum[t]-a[t]+a[t+1];
                for(len=2;len<=n;len++){
                    for(i=1;i<=n-len+1;i++){
                        j=i+len-1;
                        dp[i][j]=inf;
                        for(k=s[i][j-1];k<=s[i+1][j];k++){
                            if(dp[i][j]>dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]){
                                dp[i][j]=dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1];
                                s[i][j]=k;
                            }
    
                        }
                    }
    
                }
    
    
                sum[t]=sum[t]+a[t]-a[t+1];
                minx=min(minx,dp[1][n]);
            }
    
    
            printf("%d
    ",minx);
    
        }
        return 0;
    }
    
    
    
    




    
    

    
                
    
  • 相关阅读:
    MVC5+EF6 入门完整教程七
    MVC5+EF6 入门完整教程六
    MVC5+EF6 入门完整教程五
    MVC5+EF6 入门完整教程四
    MVC5 + EF6 完整入门教程三
    MVC5 + EF6 入门完整教程二
    MVC5 + EF6 入门完整教程
    最短路径简析
    PAT 1147 Heaps
    PAT 1146 Topological Order
  • 原文地址:https://www.cnblogs.com/herumw/p/9464711.html
Copyright © 2011-2022 走看看