zoukankan      html  css  js  c++  java
  • 区间DP:石子归并

    题目描述 
    Description

    有n堆石子排成一列,每堆石子有一个重量w[i], 每次合并可以合并相邻的两堆石子,一次合并的代价为两堆石子的重量和w[i]+w[i+1]。问安排怎样的合并顺序,能够使得总合并代价达到最小。

    输入描述 Input Description

    第一行一个整数n(n<=100)

    第二行n个整数w1,w2...wn  (wi <= 100)

    输出描述 Output Description

    一个整数表示最小合并代价

    样例输入 Sample Input

    4

    4 1 1 4

    样例输出 
    Sample Output
    18

    这道题可以轻松地找出状态转移方程f[i,j]:=max{f[i,k]+f[k+1,j]}+sum[i,j];

    但问题是如何递推是个问题,
    1:若正推,for i:=1 to n do
    for j:=i to n do
    这样的话,递推顺序为(1,1),(1,2),(1,3),(1,4),(2,2).....
    中间还有未求的量。
    2:若逆推,顺序为(n,n),(n-1,n-1),(n-1,n),(n-2,n-2)....。故应逆推。

    还有一点要注意,就是当前所求的区间的前趋i,后趋j,和中间变量k有(i=j-1=k)时f[i,j]:=stone[i]+stone[j];

    var num:longint;
    stone:array[1..100]of integer;
    i,j,k,l,n,max:longint;
    sum:array[1..100,1..100]of longint;
    f:array[1..100,1..100]of longint;
    
    
    begin fillchar(stone,sizeof(stone),0);
    fillchar(sum,sizeof(sum),0);
    fillchar(f,sizeof(f),$7F);
    readln(n);
    for i:=1 to n do
    read(stone[i]);
    for i:=1 to n do
    for j:=i to n do
    for k:=i to j do
    sum[i,j]:=sum[i,j]+stone[k];
    for i:=1 to n do
    f[i,i]:=0;
    for i:=n downto 1 do
    for j:=i to n do
    for k:=i to j-1 do
    if (i=k)and(k=j-1)
    then begin if f[i,j]>f[i,k]+f[k+1,j]+sum[i,j]
    then f[i,j]:=stone[i]+stone[j];
    end
    else begin if f[i,j]>f[i,k]+f[k+1,j]+sum[i,j]
    then f[i,j]:=f[i,k]+f[k+1,j]+sum[i,j];
    end;
    writeln(f[1,n]);
    end.
  • 相关阅读:
    绑定下拉列表
    部署WSP出现错误—已在此服务器场中安装ID为XXXXX的功能
    sharepoint权限
    sql日期操作
    Sql脚本动态创建表
    sharepoint中添加子网站
    解决未知的服务器标记“asp:ListView”。
    sharepoint中新添加页面
    vue中使用localStorage存储信息
    Js事件大全
  • 原文地址:https://www.cnblogs.com/spiderKK/p/4230641.html
Copyright © 2011-2022 走看看