『嗨威说』算法设计与分析 - 动态规划思想小结(HDU 4283 You Are the One)

本文索引目录:

一、动态规划的基本思想

二、数字三角形、最大子段和(PTA)递归方程

三、一道区间动态规划题点拨升华动态规划思想

四、结对编程情况

一、动态规划的基本思想:

  1.1  基本概念:

  动态规划算法简单说,利用拆解问题思想,定义问题状态和状态之间的关系,使得问题能够以递推或者是分治的方式去解决。
  动态规划算法的基本思想与分治法很相似,将待求解的问题分解为若干个子问题,前一子问题的解,为后一子问题的求解所依赖。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。依次解决各子问题,最后一个子问题就是初始问题的解。

  1.2  使用条件:

  (1)具有最优子结构

具有最优子结构也可能是适合用贪心的方法求解。

注意要确保我们考察了最优解中用到的所有子问题。

1、证明问题最优解的第一个组成部分是做出一个选择;

2、对于一个给定问题,在其可能的第一步选择中,你界定已经知道哪种选择才会得到最优解。你现在并不关心这种选择具体是如何得到的,只是假定已经知道了这种选择;

3、给定可获得的最优解的选择后,确定这次选择会产生哪些子问题,以及如何最好地刻画子问题空间;

4、证明作为构成原问题最优解的组成部分,每个子问题的解就是它本身的最优解。方法是反证法,考虑加入某个子问题的解不是其自身的最优解,那么就可以从原问题的解中用该子问题的最优解替换掉当前的非最优解,从而得到原问题的一个更优的解,从而与原问题最优解的假设矛盾。

要保持子问题空间尽量简单,只在必要时扩展。 最优子结构的不同体现在两个方面: 原问题的最优解中涉及多少个子问题; 确定最优解使用哪些子问题时,需要考察多少种选择。 子问题图中每个定点对应一个子问题,而需要考察的选择对应关联至子问题顶点的边。

  (2)子问题重叠

子问题空间要足够小,即问题的递归算法会反复地求解相同的子问题,而不是一直生成新的子问题。

  1.3  使用思想:

(1)首先是拆分问题,将问题划分成一步一步这样就可以通过递推或者递归来实现。
(2)其次定义问题状态和状态之间的关系,前面拆分的步骤之间的关系,用一种量化的形式表现出来,也即状态转移方程式。

  1.4  动态规划的问题种类:

(1)背包动态规划问题

(2)区间动态规划问题

(3)有向无环图的动态规划问题

(4)树形动态规划问题

(5)状态压缩动态规划问题

(6)数位动态规划问题

(7)插头动态规划问题

(8)计数动态规划问题

(9)实时动态规划问题

(10)动态规划优化问题等

 

二、数字三角形、最大子段和(PTA)递归方程:

  数字三角形:/* 动规转移方程: dp[i][j] = temp[i][j] + max(dp[i+1][j],dp[i+1][j+1]);*/

          dp[i][j]表示第i行第j个当前已走数字最大总和。

  最大子段和:/* 动规转移方程: dp[i] = max(dp[i-1]+num[i],num[i]);*/

          dp[i]表示以num[i]作为结尾元素时的最大字段和。

三、一道区间动态规划题点拨升华动态规划思想:

2.1  题目来源:

Vjudge:https://vjudge.net/contest/112701#problem/G

2.2  题目题干:

 You Are the One  

2.3  题目大意:

  题目意思是:给定一个有序队伍,在进入舞台前,需要先进入一个狭小的黑屋子,最先进去的人最后出来,进入舞台的顺序会影响到每个人的愤怒值,每个人上台的时候的愤怒值为第k个人上场乘以自己的屌丝值,试问怎么安排人员进出狭小黑屋子能实现最小化愤怒值?

  这个问题简化来说,就是给定一个有序队列,进入一个栈中(也即题目的狭小黑屋子),然后通过不断地进栈出栈实现人员顺序调整,最后使得上台之后的所有人愤怒值总和最小。

2.4  题目思路:

  首先介绍一下区间DP:

  定义:区间dp就是在区间上进行动态规划,求解一段区间上的最优解。主要是通过合并小区间的 最优解进而得出整个大区间上最优解的dp算法。

  核心思路:既然让我求解在一个区间上的最优解,那么我把这个区间分割成一个个小区间,求解每个小区间的最优解,再合并小区间得到大区间即可。所以在代码实现上,我可以枚举区间长度len为每次分割成的小区间长度(由短到长不断合并),内层枚举该长度下可以的起点,自然终点也就明了了。然后在这个起点终点之间枚举分割点,求解这段小区间在某个分割点下的最优解。

  基本模板:

for(int len = 1;len<=n;len++){//枚举长度
        for(int j = 1;j+len<=n+1;j++){//枚举起点,ends<=n
            int ends = j+len - 1;
            for(int i = j;i<ends;i++){//枚举分割点,更新小区间最优解
                dp[j][ends] = min(dp[j][ends],dp[j][i]+dp[i+1][ends]+something);
            }
        }
    }

  本题思路:

  题意给出n个人,每个人都有他们自己的屌丝值,第k个人出场的愤怒值为(k-1)*屌丝值,现在有一个栈,可以通过栈的入栈出栈操作来实现调整队伍的方法,可以很明显的了解到这能够使用区间DP,也即把一个大的区间去转化成两个小区间,思想有点类似于分治法,对于一个人,如果他是第k个出场的,那么一定是i到i+k-1中以一种方式出场,然后这个人出场,然后i+k到j以一种方式出场,这样就分成了三个区间,[i,i]、[i+1,i+k-1]、[i+k,j]这三个区间。

令 dp[i][j] 表示从 i 到 j 这些人以一种出场顺序的最小值。

那么对于刚刚划分出来的三个区间 我们可以得到 dp[i][j] = dp[i+1][i+k-1] + (k-1)*a[i] + (sum[j]-sum[i+k-1])*k + dp[i+k][j]

dp[i+1][i+k-1] :表示先出场这一批人的最小愤怒值

(k-1)*a[i] :表示 i 出场时的愤怒值

dp[i+k][j] :表示后面这一批人的最小愤怒值

(sum[j]-sum[i+k-1])*k :表示后面这一批人需要额外加上的愤怒值

2.5  题目AC代码:

#include<bits/stdc++.h>
using namespace std;

int times;
int dp[1005][1005];
int main()
{
    ios::sync_with_stdio(false);
    cin>>times;
    for(int i = 1;i<=times;i++)
    {
        int temp;
        cin>>temp;
        int *mark = new int[temp+1];
        int *ans = new int[temp+1];
        ans[0] = 0;

        for(int i = 1;i<=temp;i++)
        {
            ans[i] = 0;
            cin>>mark[i];
            ans[i] = ans[i-1] + mark[i];
        }

        for(int i=1;i<1005;i++)
        {
            for(int j=i+1;j<1005;j++)
                dp[i][j]=999999999;
        }

        for(int d=2; d<=temp; d++) {
            for(int i=1, j=d; j<=temp; i++, j++) {
                for(int k=1; k<=j-i+1; k++) {
                    dp[i][j] = min(dp[i][j], dp[i+1][i+k-1]+dp[i+k][j]+(ans[j]-ans[i+k-1])*k+mark[i]*(k-1));
                }
            }
        }

        cout<<"Case #"<<i<<": "<<dp[1][temp]<<endl;
    }
 }

四、 结对编程情况:

  经过第一次实践合作之后,第二次的实践合作更加顺利流畅,能够让双方都能在相同思路上齐头并进,当和三木小哥哥想到一起完成了算法设计、完成代码书写、成功AC一题之后,一种喜悦感涌上心头,虽然第三题有一小点WA了,不过还是很合作默契的哈哈,感谢三木小哥哥一直包容我的错误哈哈哈哈。

  相信在下一次结对编程会愈发顺利,加油。

如有不合理的地方,请及时指正,我愿听取改正~

参考链接:https://oi-wiki.org/

原文地址:https://www.cnblogs.com/WinniyGD/p/11740362.html

时间: 2024-08-25 07:37:01

『嗨威说』算法设计与分析 - 动态规划思想小结(HDU 4283 You Are the One)的相关文章

『嗨威说』算法设计与分析 - 算法第二章上机实践报告(二分查找 / 改写二分搜索算法 / 两个有序序列的中位数)

本文索引目录: 一.PTA实验报告题1 : 二分查找 1.1 实践题目 1.2 问题描述 1.3 算法描述 1.4 算法时间及空间复杂度分析 二.PTA实验报告题2 : 改写二分搜索算法 2.1 实践题目 2.2 问题描述 2.3 算法描述 2.4 算法时间及空间复杂度分析 三.PTA实验报告题3 : 两个有序序列的中位数 3.1 实践题目 3.2 问题描述 3.3 算法描述 3.4 算法时间及空间复杂度分析 四.实验心得体会(实践收获及疑惑) 一.PTA实验报告题1 : 二分查找 1.1 实践

『嗨威说』算法设计与分析 - PTA 数字三角形 / 最大子段和 / 编辑距离问题(第三章上机实践报告)

本文索引目录: 一.PTA实验报告题1 : 数字三角形 1.1 实践题目 1.2 问题描述 1.3 算法描述 1.4 算法时间及空间复杂度分析 二.PTA实验报告题2 : 最大子段和 2.1 实践题目 2.2 问题描述 2.3 算法描述 2.4 算法时间及空间复杂度分析 三.PTA实验报告题3 : 编辑距离问题 3.1 实践题目 3.2 问题描述 3.3 算法描述 3.4 算法时间及空间复杂度分析 四.实验心得体会(实践收获及疑惑) 一.PTA实验报告题1 : 数字三角形 1.1 实践题目: 1

『嗨威说』常见的C++函数模板整理(一)

开学两天,身上的职责直接变为两个班班长,三个小组组长,哇这事情估计够我忙活了,想躲都躲不掉啊,看来我还是真招人推荐各种管理职务啊,以后要是有人推荐我当经理啊领导啊该多好哈哈哈哈.记得今天奶奶生日,很开心地给奶奶打了一通电话,这怕是我第一次给奶奶电话送生日祝福了哈哈哈,是啊,很想珍惜身边的人,但很多时候却一心想提高自己地能力而忽视了身边人,就这四年,就这四年好好提升自己,毕业出来一定要好好陪陪家里祖辈亲戚们. 今天有点特殊,我整理了一下学到这么久编程以来的一些模板和技巧,虽然还没整理完,就作为(一

算法设计与分析-动态规划

一.对动态规划算法的理解 动态规划算法与分治法很相似,相同之处是将原问题分解为若干个子问题,再根据子问题求得原问题的解.不同之处是动态规划的子问题之间不是相互独立的,经常是有重叠的.所以为了避免重复计算,可以制作一个表来记录已经解决的子问题,当再次遇到子问题时,查表即可得到答案.该算法通常用于求解具有最有性质的问题,并且其子问题也具有最优性质且重叠,即最优子结构性质和子问题重叠性质. 用动态规划算法解决该类问题的基本步骤是: 1.找出最优解的性质及结构 2.建立子问题最优值的递归关系(即写出递归

(转)常用的算法设计与分析-一夜星辰的博客

算法设计与分析 分治法 思想 1. 将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同.递归地解这些子问题,然后将各子问题的解合并得到原问题的解. 2. divide-and-conquer(P) { if(|P| <= n0)adhoc(P); divide P into samller subinstances P1,P2...,Pk; for(int i = 1;i < k;i++) { yi = divide-and-conquer(Pi); } retu

算法设计与分析 ------最近对问题与8枚硬币问题

利用减治法实现8枚硬币问题: 参考资料:http://blog.csdn.net/wwj_748/article/details/8863503    算法设计--八枚硬币问题 1 #include "stdafx.h" 2 #include <iostream> 3 #include <stdio.h> 4 using namespace std; 5 6 7 void eightcoin(int arr[]); 8 void compare(int a,in

《计算机算法设计与分析》v4 第1章 算法概述 算法实现题答案

博主今年刚上大三,正好开算法这门课.由于博主本人比较喜欢算法但又比较懒,啃不动算法导论,所以决定拿这本书下手. 这本书是王晓东的第四版<计算机算法设计与分析>.初步打算将每章后面的算法题都用代码实现. 有些题跟某个ACM题目很像,我会把该ACM题的链接贴上.有的题没OJ交所以可能是错的.如有发现,还望指出. 1-1 统计数字问题 http://poj.org/problem?id=2282 这个题要按位分解,一位一位的来处理. #include<iostream> #include

【通知】《算法设计与分析》实验课、理论课补课、考试时间、加分等安排 及 个人目标设定

Logistic回归为概率型非线性回归模型,是研究二分类观察结果与一些影响因素之间关系的一种多 变量分析方法.通常的问题是,研究某些因素条件下某个结果是否发生,比如医学中根据病人的一些症状来判断它是 否患有某种病. 在讲解Logistic回归理论之前,我们先从LR分类器说起.LR分类器,即Logistic Regression Classifier. 在分类情形下,经过学习后的LR分类器是一组权值,当测试样本的数据输入时,这组权值与测试数据按 照线性加和得到 这里是每个样本的个特征. 之后按照s

算法设计与分析基础(第3版)读书笔记(及几处翻译上的错误~~)

算法设计与分析基础(第3版) p16 in-place翻译为'在位'?'就地'更合适点 p38 amortized应翻译为'均摊','摊销'这个词简直莫名其妙(可能因为翻译是做算法交易导致的?) p64 迭代优于递归(迭代始终是增量式的,而递归就没办法增量了,除非能够dump整个运行时栈) p73 通过算法可视化得到一个更好的非递归算法(人的图像认知直觉思维?) p79 验证一个拓扑是环.星.还是团?(这个地方有点意思,因为我想到了动态的Verify) p87 凸包问题:从数据结构上讲,Set<