日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

DP专练1( [NOIP 2003]加分二叉树 + 太空梯 )

發(fā)布時間:2023/12/3 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 DP专练1( [NOIP 2003]加分二叉树 + 太空梯 ) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

我們先慢慢來

  • 加分二叉樹
    • 題目
    • 題解
      • 簡單講解前序//中序//后序遍歷
    • 代碼實現(xiàn)
  • 太空梯
    • 題目
    • 題解
    • 代碼實現(xiàn)

加分二叉樹

題目


題解

簡單講解前序//中序//后序遍歷

其實說白了,這個*序就是根root的遍歷順序
先序就是root–>left–>right
中序就是left–>root–>right
后序就是left–>right–>root

上圖:

那么這個圖很完美啊!!有兩個兒子的,又有只有左兒子的,還有只有右兒子的
先序:1 2 4 3 5
中序:4 2 1 3 5
后序:4 2 5 3 1
以講解先序遍歷順序為例:
首先找到根root=1,然后再去搜索左兒子2,這個時候2為新子樹的根,
接著搜索2的左兒子4,4是葉子節(jié)點回溯,其次搜索2的右兒子,無,回溯
回到最上面搜索1的右兒子3,然后搜索3的左兒子,空,回溯,
最后找到右兒子5,葉子節(jié)點,回溯
講解一個順序把近幾年所學(xué)的邏輯順序詞給憋完了


那么這道題其實就很水,加上數(shù)據(jù)那么小,直接暴力跑生成樹就ok了
對于搜索的這個新子樹的范圍l,r,枚舉這之間任何一個i為根的情況,
求個MAX
記錄個root=i,最后用遞歸輸出即可

代碼實現(xiàn)

#include <cstdio> #define MAXN 35 int dp[MAXN][MAXN]; int root[MAXN][MAXN]; int a[MAXN]; int n; void build ( int l, int r ) {if ( dp[l][r] ) return;if ( l > r ) {dp[l][r] = 1;return;}if ( l == r ) {dp[l][r] = a[l];root[l][r] = l;return;}for ( int i = l;i <= r;i ++ ) {build ( l, i - 1 );build ( i + 1, r );if ( dp[l][i - 1] * dp[i + 1][r] + a[i] > dp[l][r] ) {dp[l][r] = dp[l][i - 1] * dp[i + 1][r] + a[i];root[l][r] = i;}} } void print ( int l, int r ) {if ( ! root[l][r] ) return;printf ( "%d ", root[l][r] );print ( l, root[l][r] - 1 );print ( root[l][r] + 1, r ); } int main() {scanf ( "%d", &n );for ( int i = 1;i <= n;i ++ ) scanf ( "%d", &a[i] );build ( 1, n );printf ( "%d\n", dp[1][n] );print ( 1, n );return 0; }

太空梯

題目

題目描述
有一群牛要上太空。他們計劃建一個太空梯-----用一些石頭壘。他們有k(1<=k<=400)種不同類型的石頭,每一種石頭的高度為h_i(1<=h_i<=100),數(shù)量為c_i(1<=c_i<=10),并且由于會受到太空輻射,每一種石頭不能超過這種石頭的最大建造高度a_i(1<=a_i<=40000)。幫助這群牛建造一個最高的太空梯。

輸入格式
第一行為一個整數(shù)即k。第2行到第k+1行每一行有3個數(shù),代表每種類型魔法石的特征,即高度h,限制高度a和數(shù)量c。
輸出格式
一個整數(shù),即修建太空梯的最大高度。

樣例
樣例輸入
3
7 40 3
5 23 8
2 52 6
樣例輸出
48
【樣例說明】 15+21+12
最底下為3塊石頭2型,中間為3塊石頭1型,上面為6塊石頭3型。放置4塊石頭2型和3塊石頭1型是不可以的,因為頂端的石頭1型的高度超過了40的限制。

題解

這道題也是一個多重背包水題

首先肯定會想到排序,因為石頭類型的高度限制越小,肯定越往下排,往上很容易超過最高限制

然后我們就定義一個:bool類型的dp[i][j]
表示只使用1~i種類型石頭且總高度為j的剋行性,
可以湊出來并且合法就是1,反之0

dp[i][j]=max(dp[i-1][j],dp[i-1][j-k*stone[i].h]) k表示i石頭使用的個數(shù)

我們知道dp[i][j]只與i-1上一種石頭類型有關(guān)
所以我們就簡化成一維

dp[j]=max(dp[j], dp[j-k*stone[i].h])

這里還是像其他dp題一樣,j要從大到小枚舉
簡單解釋為什么;
當我們i++后要重新開始枚舉j,如果是從小到大,
因為我們是一維,就會對上一次i改變后的答案進行更改
而我們到后面的會有 j - k * stone[i].h 的操作,這個時候我們其實是需要i-1的狀態(tài),
如果從小到大狀態(tài)答案就被覆蓋了,最后ans也會出錯

代碼實現(xiàn)

#include <cstdio> #include <iostream> #include <algorithm> using namespace std; #define MAXN 405 #define MAX 40005 struct node {int h, limit, c; }stone[MAXN]; bool cmp ( node x, node y ) {return x.limit < y.limit; } int n, Max; bool dp[MAX]; int main() {scanf ( "%d", &n );for ( int i = 1;i <= n;i ++ ) {scanf ( "%d %d %d", &stone[i].h, &stone[i].limit, &stone[i].c );Max = max ( Max, stone[i].limit );}sort ( stone + 1, stone + n + 1, cmp );dp[0] = 1;for ( int i = 1;i <= n;i ++ )for ( int j = Max;j >= 0;j -- )for ( int k = 0;k <= stone[i].c;k ++ ) {if ( j < k * stone[i].h || j > stone[i].limit ) break;else dp[j] = max ( dp[j], dp[j - k * stone[i].h] );}for ( int i = Max;i >= 0;i -- )if ( dp[i] ) {printf ( "%d\n", i );break;}return 0; }

好了,就到這里吧,這只是練練手,不然怎么叫專練1呢~~

等會兒我就會攜帶著一堆毒瘤來見大家的,bye~

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的DP专练1( [NOIP 2003]加分二叉树 + 太空梯 )的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。