HLJU DP解題報告

2021-07-09 14:16:07 字數 4657 閱讀 2490

傳送門:

a題:簡單的揹包問題

題意:給你每件物品的價值和大公尺的重量和大公尺有多少袋,問我們m元錢能最多買多少大公尺。

分析:最初我們看到這個題有乙個想法就是每次買價效比最高的那個,貪心的思想去做這道題,但是我給你一組資料吧

3 15

7 3 1    **7,重量3,只有1袋

8 3 1

9 5 1

意思是3種大公尺,15這麼多的錢,有7-3,8-3,9-5這種型別的大公尺,這樣的話我們選擇價效比最高的顯然選擇9-5,這時候我們發現我們完全可以選擇7-3,8-3這個組合,得到更多的價值。

這個時候我們我們使用動態規劃的時候想到什麼呢?

我們是不是可以定義乙個dp陣列?

dp[i+1][j],代表前i件物品且j這麼多錢我們最多能得到多重的大公尺。

如果說我們這樣定義dp[i+1][j]的話,我們在選擇第i件的時候該怎麼轉移狀態呢?

我們用cost[i],gain[i]來表示這袋公尺的屬性的話,我們對於這袋大公尺只有兩種選擇,要麼買,要麼不買,不買的話dp[i+1][j]=dp[i][j],買的話就是dp[i+1][j]=dp[i][j-cost[i]]+gain[i],對嗎?那麼我們按照什麼規則進行選擇呢?這時候肯定是比較一下兩種哪個大對吧?那麼這個時候我們可以得到這個狀態轉移方程式

dp[i+1][j]=max(dp[i][j],dp[i][j-cost[i]]+gain[i]);

那麼這個時候我們還有一種情況沒有考慮到,就是我現在的錢還買不起這袋公尺的時候那麼我們就直接讓dp[i+1][j]=dp[i][j]就行了吧?

關於每種大公尺的數量的處理在**裡會寫到

**如下:

#include#include#includeusing namespace std;

#define max_n 105

int cost[max_n],gain[max_n],num[max_n],dp[max_n][max_n];

int main(void)

else dp[i+1][j]=max(dp[i+1][j],dp[i][j-k*cost[i]]+k*gain[i]);//代表我一次買k袋會怎樣}}

}printf("%d\n",dp[n][m]);

}}//想想用一維的dp陣列怎麼寫?

b題:最長公共序列問題

題意:給你兩個串,輸出這個兩串的最長公共序列的長度即可(如果讓我們繼續輸出這個公共序列是什麼怎麼辦?這個時候我們怎麼處理這個問題呢?)

分析:定義dp[i+1][j+1]表示第乙個串的前i位和第二個串的前j位的最長公共序列的長度,

如果這樣定義的話狀態該怎麼轉移呢?

顯然,如果第乙個串的第i位和第二個串的第j位相同的時候dp[i+1][j+1]=dp[i][j]+1

如果說這兩個位置不相同的時候,那麼我們是不是可以這樣

dp[i+1][j+1]=max(dp[i+1][j],dp[i][j+1])這樣呢?

**如下:

#include#include#includeusing namespace std;

#define max_n 1005

int dp[max_n][max_n];

char s[max_n],ss[max_n];

int main(void)

else

if(sum>max)

}printf("case %d:\n%d %d %d\n",ca++,max,l,r);

if(t) printf("\n");

}}

g題:最大遞增序列和問題

題意:給你乙個串,要求我們找到乙個遞增序列,且這個序列的和最大。

分析:這樣的話我們是不是可以定義dp[i+1]表示第i個數結尾的最大遞增序列的最大值,那麼我們就能很簡單的想到乙個o(n*n)的演算法呢?即訪問當前這個數的時候,去它前面找所有比它小的數的最大遞增序列的最大值,之後更新dp[i+1]即可吧?

**如下:

include#include#includeusing namespace std;

int dp[1005],a[1005];

int main(void)}}

printf("%d\n",dp[m]);

}}

k題:最大欄位和問題

題意:給你一串數,找出這串數的m段不相容的字段和,使得這m段字段和的和最大化,輸出這個最大值。

分析:**如下:

l題:模擬數塔問題

這個題怕你們不會做故意把題目寫成這樣

題意:有11個點,分別為(0—10)初始在5這個位置,現在有t個餡餅,會在特定的時間掉在特定的位置掉下,我們每一秒只能向左或向右移動乙個位置,現在問你最多能得到多少個餡餅。

分析:這個題是不是很像數塔呢?注意的是每次我們考慮好邊界條件。而且這道題是不是逆著考慮想會更好?

我們定義dp[i][j]表示最後i秒在j這個位置能得到最後t-i秒的多少餡餅,(t表示輸入的最大時間),可以看看**好好理解一下

**如下:

#include#include#includeusing namespace std;

int dp[100005][11],num[100005][11];

int main (void)

}printf("%d\n",dp[0][5]);

}}

這個題目好好想想為什麼這樣寫,對理解dp很有幫助

m題:二維最大遞增序列和問題

題意:現在有n種箱子,每種箱子有其對應的長寬高,且每種箱子有無限個,我們先在要用這些箱子搭一座塔,乙個箱子上能再放乙個箱子的要求是,這個箱子的長比上乙個箱子要小,這個箱子的寬比上乙個箱子要小,由於我們知道乙個箱子能夠旋轉,那麼乙個箱子能夠得到6種形狀,

分析:這樣的話,我們是不是可以先對一維進行排序,再對第二維dp找到以這個箱子為頂部的塔的最大高度呢?

**如下:

#include#include#includeusing namespace std;

struct nodea[200];

int cmp(node a,node b)

int dp[200];

int main(void)

}dp[i]+=a[i].c;

}printf("case %d: maximum height = %d\n",ca++,*max_element(dp,dp+k));

}}

n題:最長上公升序列問題

題意:不說了

分析:為什麼是最長上公升序列問題呢?想想吧,不能一直給答案吧。。。。

**如下:一種簡單的求上公升序列問題的方法,為什麼這樣寫?問我

#include#include#includeusing namespace std;

#define inf 3000005

int a[100005],dp[100005];

int main(void)a[1005];

int dp[1005];

int cmp(node a,node b)

int main(void)

}if(j==0) ans+=a[i].b;

}printf("%d\n",ans);

}}

p題:這是乙個很有意思的題目

題意:給我們乙個串,只有大寫字母,小寫字母,我們可以按tab鍵shift鍵來輸入大些字母。讓我們輸入最少按多少次能把這個串用電腦敲出來,且最後tab鍵得是關著的

分析:我們首先可以知道tab鍵的作用,切換大小寫,且shift鍵的作用是什麼?我們知道小寫的時候按住shift鍵再按字母可以變大寫,大寫的時候我們可以按住shift鍵再按字母可以變小寫。那麼這個時候是不是可以想到這樣一種狀態,tab鍵關著的時候,tab鍵開著的時候?dp[i+1][0]表示當前讀取到第i個tab鍵是關著的,dp[i+1][1]表示當前地區到第i個且tab鍵是開著的。這樣的話我們是不是可以找到相應的狀態轉移方程式呢?

首先我們找到第i個元素.

如果是大些字母的話

那麼 dp[i+1][0]=min(dp[i][1]+2,dp[i][0]+2);

且 dp[i+1][1]=min(dp[i][1]+1,dp[i][0]+2);

如果是小些字母的話

那麼 dp[i+1][0]=min(dp[i][1]+2,dp[i][0]+1);

且 dp[i+1][1]=min(dp[i][1]+2,dp[i][0]+2);

這樣對嗎?想想為什麼這樣

那麼初始條件是什麼呢?想想就知道了dp[0][0]=0,dp[0][1]=1(按了一下tab鍵)。

最後輸出的是什麼呢?想想應該是min(dp[n][0],dp[n][1]+1);想想為什麼要+1呢?

仔細想想這個題目是不是很有意思?

**如下:

#include#include#includeusing namespace std;

int dp[105][2];

char s[105];

int main(void)

else }}

printf("%d\n",min(dp[len][0],dp[len][1]+1));

}}

當你做完這套題時,再回首,看看原來的自己。

Block Voting 解題報告

這道題做的有點狼狽,效率不高,差一點就tle的ac了。看status裡的,ac的時間大多數都是0ms的。肯定有乙個更有效率的演算法的。下面說下我的狼狽演算法。出處 http acm.jlu.edu.cn joj showproblem.php?pid 1223 問題描述 求每個party的權值。第i...

Safebreaker 解題報告

又是吉林大學一道acm題目,題目很簡單,直接暴力解決。出處 http acm.jlu.edu.cn joj showproblem.php?pid 1718 問題描述 對乙個給定數0000 9999 根據一系列猜測,判斷這個數是否存在,存在的話,是否唯一 例如 3321,給定數 作出猜測,1223 ...

路由 解題報告

路由 問題描述 有乙個tcp ip網路 每台計算機都有乙個或多個網路介面。每個介面根據它的ip位址和子網掩碼來識別 即兩個4位元組的數,兩個字 節之間有乙個 號.子網掩碼有乙個二進位制表示法 有k個 1 然 後是 m 個 0 k m 8 4 32 如 212.220.35.77 是乙個 ip 地 址...