zoukankan      html  css  js  c++  java
  • Evanyou Blog 彩带

      题目传送门

    题目描述

    在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。

    试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分.

    输入输出格式

    输入格式:

     

    数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数.

     

    输出格式:

     

    输出共2行,第1行为最小得分,第2行为最大得分.

     

    输入输出样例

    输入样例#1: 复制
    4
    4 5 9 4

      分析:显然是用DP。

      由于是环状,我们需要把它转换为链状,那么就把存储石子的数组a[]空间开大一倍,从n+1~2*n存储的值等于1~n存储的值,那么只需要从1到n枚举链的开头即可,链尾则分别为n到2*n-1。这样计算和环状是等效的。

      那么考虑状态转移方程,设d[i][j]是将i~j堆石子合并后得到的最大值,x[i][j]是将i~j堆石子合并后得到的最小值,首先两重循环i,j枚举区间的两端,然后再加一重循环枚举断点,也就是说,i~k和k+1~j分别是要合并的两堆石子,那么状态转移方程不难想到:

      d[i][j]=max(d[i][j],d[i][k]+d[k+1][j]+a[i]+...+a[j])

      x[i][j]=min(x[i][j],x[i][k]+x[k+1][j]+a[i]+...+a[j])

      显然两种计算不冲突,可以同时进行,然后a[i]+...+a[j]可以用前缀和优化,那么这题也就解决了。

      Code:

    #include<bits/stdc++.h>
    #define Fi(i,a,b) for(int i=a;i<=b;i++)
    #define Fx(i,a,b) for(int i=a;i>=b;i--)
    using namespace std;
    const int N=1001;
    int n,a[N],s[N],d[N][N],x[N][N];
    int maxx,minn=0x3f3f3f3f;
    int main()
    {
      ios::sync_with_stdio(false);
      cin>>n;Fi(i,1,n){cin>>a[i];a[n+i]=a[i];}
      Fi(i,1,2*n)s[i]=s[i-1]+a[i];
      Fi(c,1,n){
        memset(x,0x7f,sizeof(x));
        memset(d,0,sizeof(d));
        Fi(i,c,c+n-1)d[i][i]=x[i][i]=0;
        Fx(i,c+n-2,c)Fi(j,i+1,c+n-1)Fi(k,i,j-1){
          d[i][j]=max(d[i][j],d[i][k]+d[k+1][j]+s[j]-s[i-1]);
          x[i][j]=min(x[i][j],x[i][k]+x[k+1][j]+s[j]-s[i-1]);}
        maxx=max(maxx,d[c][c+n-1]);
        minn=min(minn,x[c][c+n-1]);}
      cout<<minn<<"
    "<<maxx;return 0;
    }
  • 相关阅读:
    FreeRTOS学习目录
    ESP32随笔汇总
    FPGA开发随笔汇总
    manim在windows系统下安装
    16、频率域滤波
    15、频率域滤波基础——傅里叶变换计算及应用基础
    14、OpenCV实现图像的空间滤波——图像锐化及边缘检测
    13、OpenCV实现图像的空间滤波——图像平滑
    12、OpenCV实现图像的直方图处理
    生成预加载镜像以及设备树
  • 原文地址:https://www.cnblogs.com/cytus/p/9076523.html
Copyright © 2011-2022 走看看