1. 程式人生 > >HUD 1257 最少攔截系統 / HDU 2084 數塔 (DP)

HUD 1257 最少攔截系統 / HDU 2084 數塔 (DP)

這個星期進入DP專題。

先是基本概念。。(摘抄課件,我自重= =)

動態規劃(Dynamic Programming, DP)是解決某一類問題的一種方法,是分析問題的一種途徑,而不是一種特殊演算法(如線性規劃是一種演算法)。因此,在學習動態規劃時,除了對基本概念和方法正確地理解外,應以豐富的想象力去建立模型,用創造性的技巧去求解。

動態規劃三要素:階段,狀態,決策。

動態規劃用於解決多階段決策最優化問題,但是不是所有的最優化問題都可以用動態規劃解答呢?

一般在題目中出現求最優解的問題就要考慮動態規劃了,但是否可以用還要滿足兩個條件:

¢最優子結構(最優化原理)

當前狀態是前面狀態的完美總結

¢無後效性

什麼是無後效性呢?

就是說在狀態i求解時用到狀態j而狀態j就解有用到狀態k…..狀態N,而求狀態N時有用到了狀態i

解決動態規劃問題的一般思路

(1)模型匹配法:

最先考慮的就是這個方法了。挖掘問題的本質,如果發現問題是自己熟悉的某個基本的模型,就直接套用,但要小心其中的一些小的變動,現在考題辦都是基本模型的變形套用時要小心條件,三思而後行。這些基本模型在先面的分類中將一一介紹。

(2)三要素法

仔細分析問題嘗試著確定動態規劃的三要素,不同問題的卻定方向不同:

先確定階段的問題:數塔問題,和走路問題(詳見解題報告)

先確定狀態的問題:大多數都是先確定狀態的。

先確定決策的問題:揹包問題。(詳見解題報告)

(3)尋找規律法

(4)邊界條件法

找到問題的邊界條件,然後考慮邊界條件與它的領接狀態之間的關係。這個方法也很起效。

(5)放寬約束和增加約束

這個思想是在陳啟鋒的論文裡看到的,具體內容就是給問題增加一些條件或刪除一些條件使問題變的清晰。

HDU兩道典型例題。

先是簡單的一維狀態。比如HDU 1257,導彈攔截問題。

如果把題目換成“求最多能攔截的導彈數目”,那這道題就變得顯而易見,求最長下降子序列型別DP。

很容易想到一個複雜度為n^2的方法,狀態轉移方程:

opt[i] = max{opt[j]+1, opt[i]} (0 <= j < i, aj >= ai)

很自然想到,既然求得了最長下降子序列,那是不是求出有幾組這樣的序列,輸出組數就是答案了呢?

偏偏這樣做是Wrong Answer。舉出反例:

設導彈高度為:6 1 7 3 2

根據最初的方法求得,最長下降序列為:6 3 2/1/7,也即需要3套系統。但真正的答案是6 1/7 3 2,2套就夠了!

換個思路。每個導彈都要攔截,每發射一發攔截炮彈,下一次發射高度不能超過上一發,也就是這套系統無法攔截比上一發炮彈高度更高的導彈。如此,考慮“最長上升子序列”。有點類似找父節點,最終答案就是最長上升子序列長度。(狀態轉移方程稍作改動即可)

完整程式碼

 1 /* 2 最長上升子序列(一維形式DP)
3 opt[i]=max(opt[j])+1, opt[i]) (0<=j<i 且num[j]<=num[i]) {最長非下降序列}
4 opt[i]=max(opt[j])+1, opt[i]) (0<=j<i 且num[j]>num[i]) {最長下降序列}
5 該演算法複雜度為O(n^2)
6 */
7 #include <iostream>
8 using namespace std;
9
10 int num[30005], len[30005];
11
12 int main()
13 {
14 int m;
15 while(cin >> m) {
16 int ans = 0;
17 for(int i = 0; i < m; i++) {
18 cin >> num[i];
19 len[i] = 1;
20 }
21 for(int i = 0; i < m; i++) {
22 for(int j = 0; j < i; j++) {
23 if(num[i] > num[j]) {
24 len[i] = max(len[j] + 1, len[i]);
25 ans = max(ans, len[i]);
26 }
27 }
28 }
29 cout << ans << endl;
30 }
31 return 0;
32 }


然後是二維狀態的。HDU 2084,數塔

這道題有個特點,從上到下分析,從下至上計算。不要被二維嚇到,對於towel[i][j],我們用 i,j 表示當前數的座標。

從下至上計算時,我們需要將當前數加上它的下一層左右兩邊的最大數,得狀態轉移方程:

towel[i][j] = max(towel[i + 1][j], towel[i + 1][j + 1]) + towel[i][j];

那麼計算到最後,towel[0][0]就是答案。

(詳細分析過程可以參考一下其他教程)

完整程式碼

 1 #include <iostream>
2 using namespace std;
3
4 int towel[100][100];
5
6 int main()
7 {
8 int t;
9 cin >> t;
10 while(t--) {
11 int n;
12 cin >> n;
13 for(int i = 0; i < n; i++)
14 for(int j = 0; j <= i; j++)
15 cin >> towel[i][j];
16 for(int i = n - 2; i >= 0; i--)
17 for(int j = 0; j <= i; j++)
18 towel[i][j] = max(towel[i + 1][j], towel[i + 1][j + 1]) + towel[i][j];
19 cout << towel[0][0] << endl;
20 }
21 return 0;
22 }

相關推薦

HUD 1257 最少攔截系統 / HDU 2084 (DP)

這個星期進入DP專題。 先是基本概念。。(摘抄課件,我自重= =) 動態規劃(Dynamic Programming, DP)是解決某一類問題的一種方法,是分析問題的一種途徑,而不是一種特殊演算法(如線性規劃是一種演算法)。因此,在學習動態規劃時,除了對基本概念和方法正確地理解外,應以豐富的想象力去建

hdu 2084 dp 動態規劃

lan 必須 次循環 AC 如果 sin set main turn 開始動態規劃的學習了,先是比較基礎的,很金典的數塔。附上題目鏈接 http://acm.hdu.edu.cn/showproblem.php?pid=2084 這題的狀態轉移方程是 dp[i][

hdu 2084 (DP)

Problem Description 在講述DP演算法的時候,一個經典的例子就是數塔問題,它是這樣描述的: 有如下所示的數塔,要求從頂層走到底層,若每一步只能走到相鄰的結點,則經過的結點的數字之和最大是多少? 已經告訴你了,這是個DP的題目,你能AC嗎? Input

HDU 2084 dp

數塔 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 43433    Accepted Submissio

HDU 1257 最少攔截系統 簡單DP

容易 target ++ font put 題目 ssi pre 路徑 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1257 題目大意:求有多少個單調非遞增序列。 解題思路:經典題的變形----LIS。可以按照題意,多次dp

題解報告:hdu 1257 最少攔截系統

clas size 當前 for main 比較 http color 替代 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1257 解題思路:題目的關鍵句是“第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能超過前一發的

HDU 1257 最少攔截系統(貪心 or LIS)

分析 class mode arch urn namespace 最少攔截系統 雷達 mission 題目鏈接: http://acm.hdu.edu.cn/showproblem.php?pid=1257 最少攔截系統 Time Limit: 2000/1000 MS (

HDU - 1257 最少攔截系統

捕捉 所有 color 容易 display img 整數 ++ splay 某國為了防禦敵國的導彈襲擊,發展出一種導彈攔截系統.但是這種導彈攔截系統有一個缺陷:雖然它的第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能超過前一發的高度.某天,雷達捕捉到敵國的導彈來襲.

最少攔截系統 HDU - 1257

using ras eof 炮彈 階段 攔截 逆序數 cst 有一個 某國為了防禦敵國的導彈襲擊,發展出一種導彈攔截系統.但是這種導彈攔截系統有一個缺陷:雖然它的第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能超過前一發的高度.某天,雷達捕捉到敵國的導彈來襲.由於該系

HDU 1257 最少攔截系統 (Dilworth定理+LIS)

某國為了防禦敵國的導彈襲擊,發展出一種導彈攔截系統.但是這種導彈攔截系統有一個缺陷:雖然它的第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能超過前一發的高度.某天,雷達捕捉到敵國的導彈來襲.由於該系統還在試用階段,所以只有一套系統,因此有可能不能攔截所有的導彈.  怎麼辦呢?多搞幾套

HDU-1257-最少攔截系統 (貪心)

原題: 某國為了防禦敵國的導彈襲擊,發展出一種導彈攔截系統.但是這種導彈攔截系統有一個缺陷:雖然它的第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能超過前一發的高度.某天,雷達捕捉到敵國的導彈來襲.由於該系統還在試用階段,所以只有一套系統,因此有可能不能攔截所有的導彈. 怎麼辦呢?

HDU-1257-最少攔截系統DP

某國為了防禦敵國的導彈襲擊,發展出一種導彈攔截系統.但是這種導彈攔截系統有一個缺陷:雖然它的第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能超過前一發的高度.某天,雷達捕捉到敵國的導彈來襲.由於該系統還在試用階段,所以只有一套系統,因此有可能不能攔截所有的導彈. 怎麼辦呢?多搞幾套系統唄!你說說倒

HDU 1257 最少攔截系統

分類 HDU 貪心 題意 貪心專題 某國為了防禦敵國的導彈襲擊,發展出一種導彈攔截系統.但是這種導彈攔截系統有一個缺陷:雖然它的第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能超過前一發的高度.某天,雷達捕捉到敵國的導彈來襲.由於該系統還在試用階段,

每日三題-Day3-C(HDU 1257 最少攔截系統 最長上升子序列O(nlogn) )

原題地址 最少攔截系統 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 40250 Accepted Submi

HDU 1257 最少攔截系統 【坑題,貪心,LIS】

最少攔截系統 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S

hdu 1257 最少攔截系統【貪心 || DP——LIS】

#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int maxn = 1000+10; const int INF = 30000+10; //導彈高度

HDU 1257 最少攔截系統 LIS

         某國為了防禦敵國的導彈襲擊,發展出一種導彈攔截系統.但是這種導彈攔截系統有一個缺陷:雖然它的第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能超過前一發的高度.某天,雷達捕捉到敵國的導彈來襲.由於該系統還在試用階段,所以只有一套系統,因此有可能不能攔截

hdoj 1257最少攔截系統

ont pop popu main 不能 post tdi div -s  /*最少攔截系統 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768

1257 最少攔截系統

某國為了防禦敵國的導彈襲擊,發展出一種導彈攔截系統.但是這種導彈攔截系統有一個缺陷:雖然它的第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能超過前一發的高度.某天,雷達捕捉到敵國的導彈來襲.由於該系統還在試用階段,所以只有一套系統,因此有可能不能攔截所有的

杭電1257--最少攔截系統

題目描述: 解析: 這道題的題意容易讓人產生誤解,正確的解析–舉個例子: 輸入: 6 7 3 5 1 2 1 那麼就需要兩套反導系統,分別是:7 3 2 1 和 5 1 這道題的本質其實可以理解為最長上升子序列問題,引用一段話說明轉化的思想: 這道題讓求