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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

入门-动态规划

發布時間:2025/3/16 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 入门-动态规划 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

入門-動態規劃

  • 1. [分梨](http://acm.zzu.edu.cn/problem.php?id=1163)
      • 解析 遞歸分配
      • AC
  • 2. 最大公共子序列
  • 3. [最大子段和](http://acm.hdu.edu.cn/showproblem.php?pid=1003)
      • 解析
      • AC
  • 4. [最大子陣和](http://acm.hdu.edu.cn/showproblem.php?pid=1081)
      • 解析
      • AC
  • 5. [母牛的故事](http://acm.hdu.edu.cn/showproblem.php?pid=2018)
      • 解析
      • AC
  • 6. [數塔](http://acm.hdu.edu.cn/showproblem.php?pid=2084)
      • 解析
      • AC
  • 7. [一只小蜜蜂](http://acm.hdu.edu.cn/showproblem.php?pid=2044)
      • 解析
      • AC
  • 8. [折線分割平面](http://acm.hdu.edu.cn/showproblem.php?pid=2050)
      • 解析
      • AC
  • 9. [獻給杭電五十周年校慶的禮物](http://acm.hdu.edu.cn/showproblem.php?pid=1290)
      • 解析
      • AC

1. 分梨

題目描述
小明非常喜歡吃梨,有一天他得到了ACMCLUB送給他的一筐梨子。由于他比較仗義,就打算把梨子分給好朋友們吃。現在他要把M個梨子放到N個盤子里面(我們允許有的盤子為空),你能告訴小明有多少種分法嗎?(請注意,例如有三個盤子,我們將5,1,1和1,1,5,視為同一種分法)

輸入
輸入包含多組測試樣例。每組輸入的第一行是一個整數t。
接下來t行,每行輸入兩個整數M和N,代表有M個梨和N個盤子。(M和N均大于等于0)

輸出
對于每對輸入的M和N,輸出有多少種方法。

樣例輸入

1
7 3

樣例輸出

8

解析 遞歸分配

M個梨, N個盤子的分法 dp(m, n){if (只有一個盤子 || 沒有梨)只有一種分法;if (盤子N比梨M多)則最多用M個盤子, dp(m,n) = dp(m,m);else 如果每個至少一個梨, 則dp(m-n, n)如果有一個盤子為空, 則dp(m, n-1)dp(m, n) = dp(m, n-1) + dp(m-n, n)}

AC

#include<stdio.h> int c(int x,int y) { if(y == 1 || x == 0)return 1;if(x<y) return c(x,x);elsereturn c(x,y-1)+c(x-y,y); }int main() {int t,n,m;while(scanf("%d",&t)!=EOF){while(t--){scanf("%d%d",&m,&n);printf("%d\n",c(m,n));}} return 0; }

2. 最大公共子序列

見之前的博客

3. 最大子段和

Problem Description
Given a sequence a[1],a[2],a[3]…a[n], your job is to calculate the max sum of a sub-sequence. For example, given (6,-1,5,4,-7), the max sum in this sequence is 6 + (-1) + 5 + 4 = 14.

Input
The first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines follow, each line starts with a number N(1<=N<=100000), then N integers followed(all the integers are between -1000 and 1000).

Output
For each test case, you should output two lines. The first line is “Case #:”, # means the number of the test case. The second line contains three integers, the Max Sum in the sequence, the start position of the sub-sequence, the end position of the sub-sequence. If there are more than one result, output the first one. Output a blank line between two cases.

Sample Input

2
5 6 -1 5 4 -7
7 0 6 -1 1 -6 7 -5

Sample Output

Case 1:
14 1 4

Case 2:
7 1 6

解析

sum, maxsum = M[n-1] for auto m : M[]:sum = max(sum+m, m)if sum >= maxsum:maxsum = sum

AC

#include <iostream> #include <cstring>using namespace std;int M[100005], arr[100005]; int l, r; int maxSubArr(int D[], int n){int i, sum = 0, maxsum = D[n-1];l = n-1;for (i=n-1; i>=0; i--){if (sum > 0){sum = sum + D[i];}else{sum = D[i];}if (sum >= maxsum) { //If there are more than one result, output the first one.maxsum = sum;l = i;}}return maxsum; }int main(){int T, N;cin>>T;for (int t=1; t<=T; t++){cin>>N;for (int i=0; i<N; i++){cin>>M[i];}int ans = maxSubArr(M, N);cout<<"Case "<<t<<":"<<endl;int s = 0;for (int i = l; i<N; i++){s += M[i];if (s == ans){r=i;break;}}cout<<ans<<" "<<l+1<<" "<<r+1<<endl;if (t<T){cout<<endl;}}return 0;}

4. 最大子陣和

Problem Description
Given a two-dimensional array of positive and negative integers, a sub-rectangle is any contiguous sub-array of size 1 x 1 or greater located within the whole array. The sum of a rectangle is the sum of all the elements in that rectangle. In this problem the sub-rectangle with the largest sum is referred to as the maximal sub-rectangle.

As an example, the maximal sub-rectangle of the array:

0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2

is in the lower left corner:

9 2
-4 1
-1 8

and has a sum of 15.

Input
The input consists of an N x N array of integers. The input begins with a single positive integer N on a line by itself, indicating the size of the square two-dimensional array. This is followed by N 2 integers separated by whitespace (spaces and newlines). These are the N 2 integers of the array, presented in row-major order. That is, all numbers in the first row, left to right, then all numbers in the second row, left to right, etc. N may be as large as 100. The numbers in the array will be in the range [-127,127].

Output
Output the sum of the maximal sub-rectangle.

Sample Input

4
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2

Sample Output

15

解析

這一題可以借助上一題的思路,把求最大子陣轉化為求最大子段和,也就是變成一維情況。 (以第一行最為開始)先求第一行的最大和;將第二行數據加到第一行,再求此時的最大值;再將下一行加上去,求最大值.....; .最終得到第一列到最后一列的最大值;還要計算第二行到最后一行的最大和,第三行到最后一行的最大和;fun(){ //求最大子段和 }for i = 0 : N #第i行到j行最大子陣和# 第一次循環結束,我們得到的是第一行到第N行的N x M的最大子陣和(N是行數,M是列數,M由fun()決定)# 第二次循環結束,我們得到的是第二行到第N行的N-1 x M的最大子陣和for j = i : N 把第j行加到array上:arry[k] = M[j][k]計算array的最大子段和:fun(array)

AC

#include <iostream> #include <cstring>using namespace std;int M[105][105], arr[105]; int maxSubArr(int D[], int n){int sum=0, maxsum=D[0];for (int i=0; i<n; i++){if (sum>0){sum = sum + D[i];}else{sum = D[i];}if (sum > maxsum) maxsum = sum;}return maxsum; }int main(){int N;while(scanf("%d", &N) != EOF){//注意輸入for (int i=0; i<N; i++){for (int j=0; j<N; j++){cin>>M[i][j];}}int maxsubrec = M[0][0];for (int i=0; i<N; i++){memset(arr, 0, sizeof(arr));for (int j=i; j<N; j++){for (int k=0; k<N; k++){arr[k] += M[j][k];}int maxsubarr = maxSubArr(arr, N);if (maxsubarr > maxsubrec) maxsubrec = maxsubarr;} }cout<<maxsubrec<<endl;}return 0;}

5. 母牛的故事

Problem Description
有一頭母牛,它每年年初生一頭小母牛。每頭小母牛從第四個年頭開始,每年年初也生一頭小母牛。請編程實現在第n年的時候,共有多少頭母牛?

Input
輸入數據由多個測試實例組成,每個測試實例占一行,包括一個整數n(0<n<55),n的含義如題目中描述。
n=0表示輸入數據的結束,不做處理。

Output
對于每個測試實例,輸出在第n年的時候母牛的數量。
每個輸出占一行。

Sample Input

2
4
5
0

Sample Output

2
4
6

解析

f(n) = f(n-1) + f(n-3)

AC

#include<stdio.h> //遞歸 int sum(int n) {if (n <= 4) return n;else return (sum(n-1) + sum(n - 3)); } int main() {int n;while (~scanf("%d", &n) != EOF&&n!=0)printf("%d\n", sum(n));getchar();return 0; }

6. 數塔

Problem Description
在講述DP算法的時候,一個經典的例子就是數塔問題,它是這樣描述的:

有如下所示的數塔,要求從頂層走到底層,若每一步只能走到相鄰的結點,則經過的結點的數字之和最大是多少?

已經告訴你了,這是個DP的題目,你能AC嗎?

Input
輸入數據首先包括一個整數C,表示測試實例的個數,每個測試實例的第一行是一個整數N(1 <= N <= 100),表示數塔的高度,接下來用N行數字表示數塔,其中第i行有個i個整數,且所有的整數均在區間[0,99]內。

Output
對于每個測試實例,輸出可能得到的最大和,每個實例的輸出占一行。

Sample Input

1
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5

Sample Output

30

解析

遞推公式:DP[i][j] = M[i][j] + max(DP[i+1][j], DP[i+1][j+1]) 自底向上計算到塔頂,得到的結果即為最大和

AC

#include<iostream> #include<algorithm> #include<cstring> using namespace std;int main() {int a[105][105];int t, n, i, j;while(cin>>t){while(t--){cin>>n;memset(a,0,sizeof(a));for(i=0; i<n; i++)for(j=0; j<=i; j++)cin>>a[i][j];for(i=n-2; i>=0; i--)for(j=0; j<=i; j++)a[i][j] = a[i][j] + max(a[i+1][j], a[i+1][j+1]);cout<<a[0][0]<<endl;}}return 0; }

7. 一只小蜜蜂

Problem Description
有一只經過訓練的蜜蜂只能爬向右側相鄰的蜂房,不能反向爬行。請編程計算蜜蜂從蜂房a爬到蜂房b的可能路線數。
其中,蜂房的結構如下所示。

Input
輸入數據的第一行是一個整數N,表示測試實例的個數,然后是N 行數據,每行包含兩個整數a和b(0<a<b<50)。

Output
對于每個測試實例,請輸出蜜蜂從蜂房a爬到蜂房b的可能路線數,每個實例的輸出占一行。

Sample Input

2
1 2
3 6

Sample Output

1
3

解析

思路1:局部最優解得到全局最優解 蜂房5路線 = 蜂房3的路線 + 蜂房4的路線 蜂房6路線 = 蜂房4的路線 + 蜂房5的路線 。。。 蜂房n路線 = 蜂房n-2的路線 + 蜂房n-1的路線 斐波那契數列思路2:枚舉 1->2 (1種):1->2; 1->3 (2種): 1->2->3; 1->3; 1->4 (3種): 1->2->4; 1->2->3->4; 1->3->4; 1->5 (5種): 1->2->3->5; 1->3->5; 1->2->4->5; 1->2->3->4->5; 1->3->4->5; 1->6 (8種): 1->4(3種)->6; 1->5(5種)->6; 得斐波那契數列唯一要注意的就是數比較大,得用long long類型

AC

#include <iostream> using namespace std;int main() {long long ans = 0, pre = 0;int T;cin>>T;while(T--){int a, b;cin>>a>>b;for (int i=2; i <= b-a+1; i++){if (i==2) {pre = 0;ans = 1;}else if (i==3) {pre = 1;ans = 2; continue;}else{ans = pre + ans;pre = ans - pre;}}cout << ans << endl;} return 0; }

8. 折線分割平面

Problem Description
我們看到過很多直線分割平面的題目,今天的這個題目稍微有些變化,我們要求的是n條折線分割平面的最大數目。比如,一條折線可以將平面分成兩部分,兩條折線最多可以將平面分成7部分,具體如下所示。

Input
輸入數據的第一行是一個整數C,表示測試實例的個數,然后是C 行數據,每行包含一個整數n(0<n<=10000),表示折線的數量。

Output
對于每個測試實例,請輸出平面的最大分割數,每個實例的輸出占一行。

Sample Input

2
1
2

Sample Output

2
7

解析

n條直線最多分平面問題 題目大致如:n條直線,最多可以把平面分為多少個區域。 析:可能你以前就見過這題目,這充其量是一道初中的思考題。但一個類型的題目還是從簡單的入手,才容易發現規律。 當有n-1條直線時,平面最多被分成了f(n-1)個區域。 則第n條直線要是切成的區域數最多,就必須與每條直線相交且不能有同一交點。 這樣就會得到n-1個交點。 這些交點將第n條直線分為2條射線和n-2條線段。 而每條射線和線斷將已有的區域一分為二。這樣就多出了2+(n-2)個區域。 故:f(n)=f(n-1)+n =f(n-2)+(n-1)+n …… =f(1)+1+2+……+n =n(n+1)/2+1根據直線分平面可知,由交點決定了射線和線段的條數,進而決定了新增的區域數。 當n-1條折線時,區域數為f(n-1)。 為了使增加的區域最多,則折線的兩邊的線段要和n-1條折線的邊,即2*(n-1)條線段相交。 那么新增的線段數為4*(n-1),射線數為2。 但要注意的是,折線本身相鄰的兩線段只能增加一個區域。 故:f(n)=f(n-1)+4(n-1)+2-1 =f(n-1)+4(n-1)+1 =f(n-2)+4(n-2)+4(n-1)+2 …… =f(1)+4+4*2+……+4(n-1)+(n-1) =2n^2-n+1

AC

#include<iostream> using namespace std;int main() {int num,k;cin>>num;while(num--){cin>>k;cout<<2*k*k-k+1<<endl;}return 0; }

9. 獻給杭電五十周年校慶的禮物

Problem Description
今年是我們杭電建校五十周年,這是一個值得祝福的日子。我們該送給母校一個怎樣的禮物呢?對于目前的大家來說,最好的禮物當然是省賽中的好成績,我不能參賽,就送給學校一個DOOM III球形大蛋糕吧,這可是名牌,估計要花掉我半年的銀子呢。

想象著正式校慶那一天,校長親自操刀,把這個大蛋糕分給各地趕來祝賀的校友們,大家一定很高興,呵呵,流口水了吧…

等一等,吃蛋糕之前先考大家一個問題:如果校長大人在蛋糕上切了N刀(校長刀法極好,每一刀都是一個絕對的平面),最多可以把這個球形蛋糕切成幾塊呢?

做不出這個題目,沒有蛋糕吃的!
為-了-母-校-,為-了-蛋-糕-(不是為了DGMM,楓之羽最會浮想聯翩…),加-油-!

Input
輸入數據包含多個測試實例,每個實例占一行,每行包含一個整數n(1<=n<=1000),表示切的刀數。

Output
對于每組輸入數據,請輸出對應的蛋糕塊數,每個測試實例輸出一行。

Sample Input

1
2
3

Sample Output

2
4
8

解析

平面分割空間問題 由二維的分割問題可知,平面分割與線之間的交點有關,即交點決定射線和線段的條數,從而決定新增的區域數。 試想在三維中則是否與平面的交線有關呢? 當有n-1個平面時,分割的空間數為f(n-1)。 要有最多的空間數,則第n個平面需與前n-1個平面相交,且不能有共同的交線。即最多有n-1 條交線。 而這n-1條交線把第n個平面最多分割成g(n-1)個區域。 (g(n)為(1)中的直線分平面的個數 )此平面將原有的空間一分為二,則最多增加g(n-1)個空間。 故:f=f(n-1)+g(n-1) ps:g(n)=n(n+1)/2+1 =f(n-2)+g(n-2)+g(n-1) …… =f(1)+g(1)+g(2)+……+g(n-1) =2+(1*2+2*3+3*4+……+(n-1)n)/2+(n-1) =(1+2^2+3^2+4^2+……+n^2-1-2-3-……-n )/2+n+1 =(n^3+5n)/6+1

AC

#include <stdio.h>int main(){int n;while(scanf("%d", &n)!=EOF){printf("%d\n", (n*n*n+5*n)/6+1);}return 0; }

總結

以上是生活随笔為你收集整理的入门-动态规划的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。