动态规划浅谈

接触动态规划这么久了,简单谈一下自己对动态规划的理解。
动态规划名字听起来好像比比较高大上,可是事实上,人家就是比较高大上。(抖个机灵)

刚开始接触动态规划的时候觉得好可怕,这么复杂的问题我怎么能想的出来,这样的问题计算机怎么能够解决?

我觉得动态规划不是一种准确的算法,而是一种思想,一种特殊的搜索思想。这种思想的本质是将比较复杂的搜索问题变成一个递推题,而递推公式就是我们常常提到的状态转移方程(可能并不准确,但是我是这样理解的),或者是说将记忆化搜索的递归形式写成了递推形式。而问题的核心就是找到传说中的最优子结构和状态转移方程。

对于最优子结构,我们要思考储存状态的方式以及特殊的状态。这种状态一般比较简单容易分析。一般是最后一次,因为最后一次的干扰因素比较少,有利于找到问题的核心。而通过对最后状态的分析结合对状态的储存方式写出状态转移方程。

除此之外,对于状态的分析还需要一定的贪心的思想。

但是写出状态转移方程并不是结束,重要的是通过特殊状态的状态转移方程推广到一般情况下。这种推广方式就是我们的代码结构。
可是这种推广也不容易一眼看出来(除非你已经有很多经验或者是你做过比较相似的题),所以我们要从比较简单的情况结合我们的状态转移方程进行分析,这也是完善代码细节的关键,如初始化,边界条件,循环起止条件等。

虽然说的好像比较玄乎,但总而言之还是需要经验和感觉,养成一种这样思维的习惯。

对于比较经典的动态规划问题的整理以后再更吧,这里先讨论一道比较难以下手的区间选点问题。
Zuma CodeForces - 607B

Genos recently installed the game Zuma on his phone. In Zuma there exists a line of n gemstones, the i-th of which has color ci. The goal of the game is to destroy all the gemstones in the line as quickly as possible.
In one second, Genos is able to choose exactly one continuous substring of colored gemstones that is a palindrome and remove it from the line. After the substring is removed, the remaining gemstones shift to form a solid line again. What is the minimum number of seconds needed to destroy the entire line?
Let us remind, that the string (or substring) is called palindrome, if it reads same backwards or forward. In our case this means the color of the first gemstone is equal to the color of the last one, the color of the second gemstone is equal to the color of the next to last and so on.
Input
The first line of input contains a single integer n (1 ≤ n ≤ 500) — the number of gemstones.
The second line contains n space-separated integers, the i-th of which is ci (1 ≤ ci ≤ n) — the color of the i-th gemstone in a line.
Output
Print a single integer — the minimum number of seconds needed to destroy the entire line.

题目一看就是区间选点问题,可是我们如何选那个点呢?
仔细分析我们不难发现,就算我们用一个分点表示两个子列,可是我们并不能判断中间去掉一部分后形成的回文列应该如何处理。似乎难以下手。

接下来就是比较玄学的分析阶段了。我们仔细观察回文列,发现他们有一个共同的特征就是两端的数字相等,而一个回文列中间加一个数字还是回文列,两边加两个相同的数还是回文列。我们不难 得出

if(a[i]==a[j]) dp[i][j]=min(dp[i+1][j-1],dp[i][j]);

然后我们还要注意当两个相同的在一起的时候上面的式子可能不成立(i+1>j-1),所以我们不妨对两个在一起的情况全部分开讨论一次
然后其他部分还是根据区间选点问题进行处理
下面附AC代码

#include<cstdio>
#include<cstring>
using namespace std;int n;
int a[505];
int dp[505][505];int min(int a,int b)
{return a<b?a:b;
}
int main()
{scanf("%d",&n);memset(a,0,sizeof(a));memset(dp,0x3f,sizeof(dp));	//默认是一个很大的数for(int i=1;i<=n;i++){scanf("%d",&a[i]);dp[i][i]=1;	//对1个的时候进行处理}for(int i=1;i<=n-1;i++){if(a[i]==a[i+1]) dp[i][i+1]=1;	//将两个相邻的回文数进行处理(因为无法用上面的那个式子)else dp[i][i+1]=2;}for(int len=3;len<=n;len++)	//区间长度从3 开始,这种增加区间长度而不是循环端点的写法还是比较好理解一点{for(int i=1;i+len-1<=n;i++){int j=i+len-1;dp[i][j]=min(dp[i][j],dp[i+1][j]+1);	//因为无法处理两个相同数字在一起的情况,所以先拉出来算if(a[i]==a[i+1])dp[i][j]=min(dp[i][j],dp[i+2][j]+1);//较小一点的区间已经计算过了,可以直接使用if(a[i]==a[j])	//对于两个端点相等的情况也不能用区间选点dp的公式dp[i][j]=min(dp[i][j],dp[i+1][j-1]);for(int k=i+2;k<j;k++)if(a[i]==a[k])dp[i][j]=min(dp[i][j],dp[i+1][k-1]+dp[k+1][j]);	}}printf("%d\n",dp[1][n]);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384221.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux多线程——使用信号量同步线程

http://blog.csdn.net/ljianhui/article/details/10813469/ 信号量、同步这些名词在进程间通信时就已经说过&#xff0c;在这里它们的意思是相同的&#xff0c;只不过是同步的对象不同而已。但是下面介绍的信号量的接口是用于线程的信号量&#xff0c;注意不要跟用于进程间通信…

linux下安装erlang

1.安装Erlang编译依赖: yum -y install gcc glibc-devel make ncurses-devel openssl-devel xmlto perl wget 2.下载Erlang&#xff1a; wget http://www.erlang.org/download/otp_src_19.3.tar.gz 3.解压并安装 tar -xzvf otp_src_19.3.tar.gz cd otp_src_19.3 ./configure --…

Linux 线程同步的三种方法

http://blog.csdn.net/zsf8701/article/details/7844316 线程的最大特点是资源的共享性&#xff0c;但资源共享中的同步问题是多线程编程的难点。linux下提供了多种方式来处理线程同步&#xff0c;最常用的是互斥锁、条件变量和信号量。 一、互斥锁(mutex) 通过锁机制实现线程…

Elixir特性

iex 退出&#xff1a;Ctrl-C 或Ctrl-G再输入q 回车。 帮助文档&#xff1a;h 查看辅函数列表 h IO 查看IO模块帮助 h IO.puts 查看IO模块中的puts函数的文档 编译和运行&#xff1a;创建一个hello.exs的文件。IO.puts "hello world"    //输出hello world 使用el…

Elixir基础

值类型 整数&#xff0c;包括十进制&#xff08;1234&#xff09;、十六进制&#xff08;0xcafe&#xff09;、八进制&#xff08;0o765&#xff09;和二进制&#xff08;0b1010&#xff09; 浮点数 原子&#xff0c;原子是常量&#xff0c;用于表现某些东西的名字&#xff0c;…

C++11新特性之八——函数对象function

http://www.cnblogs.com/yyxt/p/3987717.html 详细请看《C Primer plus》(第六版中文版) http://www.cnblogs.com/lvpengms/archive/2011/02/21/1960078.html 备注&#xff1a; 函数对象&#xff1a; 尽管函数指针被广泛用于实现函数回调&#xff0c;但C还提供了一个重要的实现…

分块思想

今天学习了一个算法&#xff08;这个应该叫做算法吧&#xff1f;&#xff09;叫做分块&#xff08;和莫队&#xff0c;但是莫队还没有搞懂&#xff0c;搞懂再来写吧&#xff09; 听起来很高级&#xff0c;蒟蒻表示瑟瑟发抖。但是学完发现怎么那么像是一种变相的暴力呢。 分块思…

从零开始学C++之STL(八):函数对象、 函数对象与容器、函数对象与算法

http://blog.csdn.net/jnu_simba/article/details/9500219 一、函数对象 1、函数对象&#xff08;function object&#xff09;也称为仿函数&#xff08;functor&#xff09; 2、一个行为类似函数的对象&#xff0c;它可以没有参数&#xff0c;也可以带有若干参数。 3、任何重载…

树状数组初步理解

学习树状数组已经两周了&#xff0c;之前偷懒一直没有写&#xff0c;赶紧补上防止自己忘记&#xff08;虽然好像已经忘得差不多了&#xff09;。 作为一种经常处理区间问题的数据结构&#xff0c;它和线段树、分块一样&#xff0c;核心就是将区间分成许多个小区间然后通过对大区…

命名函数

函数体是代码块 代码块do...end是一种表达式的组织方式。 # ./times.exs下defmodule Times dodef doule(n) don * 2end end 函数调用与模式匹配 代码如下&#xff1a; # ./factorial.exs    计算阶层 defmodule Factorial dodef of(0), do: 1          #终止条件…

STL运用的C++技术(6)——函数对象

http://blog.csdn.net/wuzhekai1985/article/details/6658940?_t_t_t0.20427969420870595 STL是C标准库的重要组成部分之一&#xff0c;它不仅是一个可复用的组件库&#xff0c;更是一个包含算法与数据结构的软件框架&#xff0c;同时也是C泛型编程的很好例子。STL中运用了许多…

列表与递归

头部和尾部 [head | tail ] [1] #head 1 tail [] [head | tail ] [1, 2, 3] #head 1 tail [2, 3] [head | tail ] [] #报错 创建映射函数 我们可以使用一个函数来处理列表中的各个元素&#xff0c;如此可以接受更加复杂的处理&#xff0c;也可以…

优先队列小结

不像栈和队列&#xff0c;虽然STL有较好实现但是我们自己也可以很方便的实现&#xff0c;优先队列自己实现起来就比较复杂&#xff0c;比较浪费时间&#xff08;而且自己目前也不会233&#xff09;而优先队列因为其较好的特性经常被使用&#xff0c;因此对它的熟练掌握是做题的…

字典:散列表、散列字典、关键字列表、集合与结构体

字典 散列表和散列字典都实现了Dict的行为。Keyword模块也基本实现了&#xff0c;不同之处在于它支持重复键。 Eunm.into可以将一种类型的收集映射转化成另一种。 defmodule Sum dodef values(dict) dodict |> Dict.values |> Enum.sumend endhd [ one: 1, two: 2, thre…

C++11 学习笔记 lambda表达式

http://blog.csdn.net/fjzpdkf/article/details/50249287 lambda表达式是C11最重要也最常用的一个特性之一。lambda来源于函数式编程的概念&#xff0c;也是现代编程语言的一个特点。 一.函数式编程简介 定义&#xff1a;简单说&#xff0c;“函数式编程”是一种“编程范式”。…

Cutting Codeforces Round #493 (Div. 2)

Cutting There are a lot of things which could be cut — trees, paper, “the rope”. In this problem you are going to cut a sequence of integers. There is a sequence of integers, which contains the equal number of even and odd numbers. Given a limited bud…

Enum、Stream

Enum 其常见用法见&#xff1a;https://cloud.tencent.com/developer/section/1116852 在sort时&#xff0c;如果要获得稳定的排序结果&#xff0c;要使用< 而不是 <。 Stream Stream是延迟处理的&#xff0c;而Enum是贪婪的&#xff0c;则意味着传给它一个收集&#xff…

linux网络编程之posix 线程(三):posix 匿名信号量与互斥锁 示例生产者--消费者问题

http://blog.csdn.net/jnu_simba/article/details/9123603 一、posix 信号量 信号量的概念参见这里。前面也讲过system v 信号量&#xff0c;现在来说说posix 信号量。 system v 信号量只能用于进程间同步&#xff0c;而posix 信号量除了可以进程间同步&#xff0c;还可以线程间…

洛谷P1080-国王游戏-贪心+高精度

P1080-国王游戏 啊啊啊&#xff0c;刚才已经写了一次了&#xff0c;但是Edge浏览器不知道为什么卡住了&#xff0c;难受。 好吧&#xff0c;其实是一道可做题&#xff0c;分析得到的贪心策略就是就是将a * b小的放在前面&#xff08;其他的懒得说了&#xff09;&#xff0c;主要…

字符串与二进制

单引号字符串会被表示成整数值列表。 &#xff1f;c返回字符 c 的整数编码。下面这个例子用于解析字符列表表示法&#xff0c;该表示法用于表示一个任意的有符号的十进制数据。 defmodule Parse dodef number([ ?- | tail ]) do_number_digits(tail, 0) * -1enddef number([ ?…