zoukankan      html  css  js  c++  java
  • 石子合并问题--圆形版(区间dp)

    在圆形操场上摆放着一行共n堆的石子。现要将石子有序地合并成一堆。规定每次只能选相邻的两堆合并成新的一堆,并将新的一堆石子数记为该次合并的得分。请编辑计算出将n堆石子合并成一堆的最小得分和将n堆石子合并成一堆的最大得分。Input输入有多组测试数据。

    每组第一行为n(n<=100),表示有n堆石子,。

    二行为n个用空格隔开的整数,依次表示这n堆石子的石子数量ai(0<ai<=100)

    Output

    每组测试数据输出有一行。输出将n堆石子合并成一堆的最小得分和将n堆石子合并成一堆的最大得分。 中间用空格分开。Sample Input3

    1 2 3

    Sample Output9 11

    我写的是端点和区间长度式的。

    环形主要处理的是,如何确定断点,使环形变成我们熟知的线性。所以采用了断环为链的手法。

    将环形断开然后将其复制一条,在接上。

    如下:

    3

    1 2 3

    变成:

    1 2 3 1 2 3

    代码如下:

    #include<iostream>
    #define min(a,b)  (a)<(b)?(a):(b)
    #define max(a,b)  (a)>(b)?(a):(b)
    #define IFN 0x3f3f3f
    using namespace std;

    int dp[210][210];       //将其复制为两个
    int ff[210][210];
    int num[105];
    int sum[210];
    int main()
    {
        int n;
        cin>>n;
        for(int i=1;i<=n;i++) cin>>num[i];
        for(int i=1;i<=n+n;i++)
        sum[i]=sum[i-1]+num[(i-1)%n+1];

        for(int len=1;len<n;len++)
        {
            for(int i=1,j=len+i;j<=n+n;i++,j++)
            {
                dp[i][j]=IFN;
                for(int s=i;s<j;s++)
                {
                    dp[i][j]=min(dp[i][j], dp[i][s]+dp[s+1][j]+sum[j]-sum[i-1]);
                    ff[i][j]=max(ff[i][j], ff[i][s]+ff[s+1][j]+sum[j]-sum[i-1]);
                }
            }
        }
        int a=IFN;  int b=0;
        for(int i=1;i<=n;i++)
        {
            a=min(a, dp[i][i+n-1]);
            b=max(b, ff[i][i+n-1]);
        }
        cout<<a<<" "<<b<<endl;
        return 0;
    }

  • 相关阅读:
    cadence中画焊盘注意事项
    频率带宽解释
    一种RC滤波电路的验证
    24L01-2.4G无线传输模块调节记录
    51中xdata,idata,data,pdata的区别
    调试24L01经验总结
    将scl分频
    I2C详细介绍
    汽车电源系统概述
    PCB命名规则-allegro
  • 原文地址:https://www.cnblogs.com/damaoranran/p/9130552.html
Copyright © 2011-2022 走看看