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\n",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\n",minx); }
return 0;
}


												

zjnu1181 石子合并【基础算法・动态规划】——高级的更多相关文章

  1. BZOJ-3229 石子合并 GarsiaWachs算法

    经典DP?稳T 3229: [Sdoi2008]石子合并 Time Limit: 3 Sec Memory Limit: 128 MB Submit: 426 Solved: 202 [Submit] ...

  2. 洛谷 P5569 [SDOI2008]石子合并 GarsiaWachs算法

    石子合并终极通用版 #include<bits/stdc++.h> using namespace std ; ]; int n,t,ans; void combine(int k) { ...

  3. POJ 1738 石子合并2 GarsiaWachs算法

    石子合并(GarsiaWachs算法) 只能用该算法过!!! 详解看代码 //#pragma comment(linker, "/STACK:167772160")//手动扩栈~~ ...

  4. CH5301 石子合并【区间dp】

    5301 石子合并 0x50「动态规划」例题 描述 设有N堆沙子排成一排,其编号为1,2,3,…,N(N<=300).每堆沙子有一定的数量,可以用一个整数来描述,现在要将这N堆沙子合并成为一堆, ...

  5. 【BZOJ 3229】 3229: [Sdoi2008]石子合并 (GarsiaWachs算法)

    3229: [Sdoi2008]石子合并 Description 在一个操场上摆放着一排N堆石子.现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合 ...

  6. 石子合并(直线版+环形版)&(朴素写法+四边形优化+GarsiaWachs算法)

    石子合并-直线版 (点击此处查看题目) 朴素写法 最简单常见的写法就是通过枚举分割点,求出每个区间合并的最小花费,从而得到整个区间的最小花费,时间复杂度为O(n^3),核心代码如下: ; i < ...

  7. PHP基础算法

    1.首先来画个菱形玩玩,很多人学C时在书上都画过,咱们用PHP画下,画了一半. 思路:多少行for一次,然后在里面空格和星号for一次. <?php for($i=0;$i<=3;$i++ ...

  8. BZOJ 3229: [Sdoi2008]石子合并

    3229: [Sdoi2008]石子合并 时间限制: 3 Sec  内存限制: 128 MB提交: 497  解决: 240[提交][][] 题目描述 在一个操场上摆放着一排N堆石子.现要将石子有次序 ...

  9. 石子合并(四边形不等式优化dp) POJ1160

    该来的总是要来的———————— 经典问题,石子合并. 对于 f[i][j]= min{f[i][k]+f[k+1][j]+w[i][j]} From 黑书 凸四边形不等式:w[a][c]+w[b][ ...

随机推荐

  1. 关联实现上-jsonpath取值

    举例子: demo01.py import jsonimport requestsimport jsonpathsession = requests.session()get_param_dict={ ...

  2. 内存性能测试 Memtester+mbw

    Memtester简单介绍 Memtester主要是捕获内存错误和一直处于很高或者很低的坏位, 其测试的主要项目有随机值,异或比较,减法,乘法,除法,与或运算等等. 通过给定测试内存的大小和次数, 可 ...

  3. 【Linux】if中的逻辑运算符怎么在linux的帮助中看到

    今天在写shell的时候,突然想查看下if相关的一些逻辑运算的,像-f -d之类的这种 于是man if  或者if --help 可是返回的信息却都无济于事,一点帮助都没有 回想一下,if中调的判断 ...

  4. Getshell

    GetShell 常用免杀大法 一.编码大法 (1).一句话马子本身采用编码 原文:<?php @eval($_GET(a)):?> 转码后:在提交的post的时候可以直接使用\u0026 ...

  5. oracle新增ID主键列,如何补全旧数据的ID值

    1.创建SEQUENCE CREATE SEQUENCE MONKEY.TEST_ADD_IDCOL_ID CACHE 100; 2.新增表栏位 ALTER TABLE MONKEY.TEST_ADD ...

  6. 转 5 jmeter性能测试小小的实战

    5 jmeter性能测试小小的实战   项目描述 被测网址:www.sogou.com指标:相应时间以及错误率场景:线程数 20.Ramp-Up Period(in seconds) 10.循环次数 ...

  7. XV6学习(1) Lab util

    正在学习MIT的6.S081,把做的实验写一写吧. 实验的代码放在了Github上. 第一个实验是Lab util,算是一个热身的实验,没有涉及到系统的底层,就是使用系统调用来完成几个用户模式的小程序 ...

  8. Navicat 创建mysql存过、定时执行存过

    创建存过: 使用Navicat for MySQL工具创建存储过程步骤: 1. 新建函数(选择函数标签 -> 点击新建函数): 2.输入函数的参数个数.参数名.参数类型等: 3.编写存储过程: ...

  9. C#高级编程第11版 - 第九章 索引

    [1]9.1 System.String 类 String类中关键的方法.如替换,比较等. [2]9.1.1 构建字符串 1.String类依然有一个缺点:因为它是不可变的数据类型,这意味当你初始化一 ...

  10. C#高级编程第11版 - 第七章 索引

    [1]7.1 相同类型的多个对象 1.假如你需要处理同一类型的多个对象,你可以使用集合或者数组. 2.如果你想使用不同类型的不同对象,你最好将它们组合成class.struct或者元组. [2]7.2 ...