動態規劃淺談

接觸動態規劃這么久了,簡單談一下自己對動態規劃的理解。
動態規劃名字聽起來好像比比較高大上,可是事實上,人家就是比較高大上。(抖個機靈)

剛開始接觸動態規劃的時候覺得好可怕,這么復雜的問題我怎么能想的出來,這樣的問題計算機怎么能夠解決?

我覺得動態規劃不是一種準確的算法,而是一種思想,一種特殊的搜索思想。這種思想的本質是將比較復雜的搜索問題變成一個遞推題,而遞推公式就是我們常常提到的狀態轉移方程(可能并不準確,但是我是這樣理解的),或者是說將記憶化搜索的遞歸形式寫成了遞推形式。而問題的核心就是找到傳說中的最優子結構和狀態轉移方程。

對于最優子結構,我們要思考儲存狀態的方式以及特殊的狀態。這種狀態一般比較簡單容易分析。一般是最后一次,因為最后一次的干擾因素比較少,有利于找到問題的核心。而通過對最后狀態的分析結合對狀態的儲存方式寫出狀態轉移方程。

除此之外,對于狀態的分析還需要一定的貪心的思想。

但是寫出狀態轉移方程并不是結束,重要的是通過特殊狀態的狀態轉移方程推廣到一般情況下。這種推廣方式就是我們的代碼結構。
可是這種推廣也不容易一眼看出來(除非你已經有很多經驗或者是你做過比較相似的題),所以我們要從比較簡單的情況結合我們的狀態轉移方程進行分析,這也是完善代碼細節的關鍵,如初始化,邊界條件,循環起止條件等。

雖然說的好像比較玄乎,但總而言之還是需要經驗和感覺,養成一種這樣思維的習慣。

對于比較經典的動態規劃問題的整理以后再更吧,這里先討論一道比較難以下手的區間選點問題。
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.pswp.cn/news/384221.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384221.shtml
英文地址,請注明出處:http://en.pswp.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([ ?…