code2102 石子归并2

划分dp

注意环形,需要把原数复制成两份再进行,详见:

http://www.cnblogs.com/FuTaimeng/p/5427426.html

初始条件:dp[i][i]=0

转移方程:dp[i][j] = max/min{ dp[i][u]+dp[u+1][j]+sum(i,j) }

答案:max/min{ dp[i][i+n-1] }    i=1 to n+1

代码如下:

#include<iostream>
#include<cstring>
#define Size 105
using namespace std;

int n;
int a[Size];
int dp1[Size][Size];//min
int dp2[Size][Size];//max
int sum[Size]; 

inline int s(int l,int r){return sum[r]-sum[l-1];}

int main(){
    memset(dp1,0x3f,sizeof(dp1));
    memset(dp2,-1,sizeof(dp2));

    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        a[i+n]=a[i];
    }
    for(int i=1;i<=2*n;i++){
        sum[i]=sum[i-1]+a[i];
        dp1[i][i]=dp2[i][i]=0;
    }
    for(int i=1;i<n*2;i++){
        dp1[i][i+1]=dp2[i][i+1]=a[i]+a[i+1];
    }

    for(int len=3;len<=n;len++){
        for(int i=1;i+len-1<=n*2;i++){
            int j=i+len-1;
            //dp1[i][j]=min(dp1[i+1][j],dp1[i][j-1])+s(i,j);
            //dp2[i][j]=max(dp2[i+1][j],dp2[i][j-1])+s(i,j);
            for(int u=i;u<j;u++){
                dp1[i][j]=min(dp1[i][j], dp1[i][u]+dp1[u+1][j]+s(i,j));
                dp2[i][j]=max(dp2[i][j], dp2[i][u]+dp2[u+1][j]+s(i,j));
            }
            //cout<<i<<","<<j<<":"<<dp1[i][j]<<"  "<<dp2[i][j]<<endl;
        }
        //cout<<endl;
    }

    int ans1=0x3f3f3f3f,ans2=-0x3f3f3f3f;
    for(int i=1;i<=n+1;i++){
        ans1=min(ans1,dp1[i][i+n-1]);
        ans2=max(ans2,dp2[i][i+n-1]);
    }

    cout<<ans1<<endl;
    cout<<ans2<<endl;

    return 0;
} 
时间: 2024-12-01 10:29:06

code2102 石子归并2的相关文章

3002 石子归并 3

时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 有n堆石子排成一列,每堆石子有一个重量w[i], 每次合并可以合并相邻的两堆石子,一次合并的代价为两堆石子的重量和w[i]+w[i+1].问安排怎样的合并顺序,能够使得总合并代价达到最小. 输入描述 Input Description 第一行一个整数n(n<=3000) 第二行n个整数w1,w2...wn  (wi <= 3000) 输出描述 Outpu

1048 石子归并

1048 石子归并 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 有n堆石子排成一列,每堆石子有一个重量w[i], 每次合并可以合并相邻的两堆石子,一次合并的代价为两堆石子的重量和w[i]+w[i+1].问安排怎样的合并顺序,能够使得总合并代价达到最小. 输入描述 Input Description 第一行一个整数n(n<=100) 第二行n个整数w1,w2...wn  (wi <= 100) 输出描述 Output Des

石子归并(dp)

石子归并 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 89  Solved: 22 [Submit][Status][Web Board] Description 现在有n堆石子,第i堆有ai个石子.现在要把这些石子合并成一堆,每次只能合并相邻两个,每次合并的代价是两堆石子的总石子数.求合并所有石子的最小代价. Input 第一行包含一个整数T(T<=50),表示数据组数. 每组数据第一行包含一个整数n(2<=n<=100),表示石子的

AC日记——石子归并 51nod 1021

石子归并 思路: 经典动态规划——归并类问题: 我们把状态划为n个,即1-n的n个长度为n个状态: 那么,每个长度为i的状态都可以由i-1个长度为i-1的状态推出: 所以,dp转移方程: dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]); 来,上代码: #include <cstdio> #include <cstring> #include <iostream> #include <algori

codevs 2102 石子归并2

传送门 2102 石子归并 2 时间限制: 10 s 空间限制: 256000 KB 题目等级 : 黄金 Gold 题目描述 Description 在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分.试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分. 输入描述 Input Description 数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的

51Nod - 1021 石子归并

51Nod -  1021 石子归并 N堆石子摆成一条线.现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的代价.计算将N堆石子合并成一堆的最小代价. 例如: 1 2 3 4,有不少合并方法 1 2 3 4 => 3 3 4(3) => 6 4(9) => 10(19) 1 2 3 4 => 1 5 4(5) => 1 9(14) => 10(24) 1 2 3 4 => 1 2 7(7) => 3 7

51nod 1021 石子归并(dp)

51nod 1021 石子归并 题解:从i到j合并的最小值:dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j] + sum[j] - sum[i-1]); 最后dp[1][n]即为所求结果. 1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #define CLR(a,b) memset((a),(b),sizeof((a))) 5 using name

合并类动态规划,石子归并,合并石子解题报告

石子归并问题 1:任意版 有N堆石子,现要将石子有序的合并成一堆,规定如下:每次只能移动任意的2堆石子合并,合并花费为将的一堆石子的数量.设计一个算法,将这N堆石子合并成一堆的总花费最小(或最大). 此类问题比较简单,就是哈夫曼编码的变形,用贪心算法即可求得最优解.即每次选两堆最少的,合并成新的一堆,直到只剩一堆为止.证明过程可以参考哈夫曼的证明过程. 2.链式归并 问题描述 设有N堆沙子排成一排,其编号为1,2,3,-,N(N<=100).每堆沙子有一定的数量.现要将N堆沙子并成为一堆.归并的

codevs 1048石子归并

传送门 1048 石子归并 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 有n堆石子排成一列,每堆石子有一个重量w[i], 每次合并可以合并相邻的两堆石子,一次合并的代价为两堆石子的重量和w[i]+w[i+1].问安排怎样的合并顺序,能够使得总合并代价达到最小. 输入描述 Input Description 第一行一个整数n(n<=100) 第二行n个整数w1,w2...wn  (wi <= 100) 输出描述 Output