小白的oj历程:动态规划

1、 冬冬爬楼梯

题目描述

冬冬爬楼梯,一步可以1级,也可以爬2级、3级。冬冬很可爱,每到一处楼梯处,他都想知道直完这个楼梯有多少种走法。但由于有的时候楼梯级数太多,可能是个天文数字,很显然,对于还处于小学5年级的冬冬是不太现实的。聪明的你,能帮冬冬实现这个愿望吗?

输入

多组测试数据,每组测试数据一行一个整数n (1<=n<=3000)

输出

对于每组测试数据,输出一个整数,为n级楼梯冬冬走完的方法数。

样例输入 复制

1
2
3

样例输出 复制

1
2
4

#include<bits/stdc++.h>
using namespace std;
#define MAXSIZE 3000
string arr[MAXSIZE]={"1","2","4"};
int n=0;
string High_cal(string a, string b){
    int L,S;
    string LL,SS,new_str;
    if(a.size()>b.size()){
        L=a.size(),S=b.size(),LL=a,SS=b;
    }
    else {
        L=b.size(),S=a.size(),LL=b,SS=a;
    }
    new_str=LL;
    for(int i=L-1,j=S-1;j>=0;j--){
        new_str[i--]=LL[i]+SS[j]-'0';
    }
    for(int i=L-1,j=S-1;i>=0;j--,i--){
        if(new_str[i]>'9') {
            if(L==S&&j==0){
                new_str[i]=new_str[i]-'9'+'0'-1;
                new_str='1'+new_str;
                return new_str;
            }                
            new_str[i]=new_str[i]-'9'+'0'-1;
            new_str[i-1]+=1;
        }
    }
    return new_str;
}
int main(){
    for(int i=3;i<3000;i++){
        arr[i]=High_cal(High_cal(arr[i-3],arr[i-2]),arr[i-1]);
    }
while(cin>>n){
cout<<arr[n-1]<<endl;
}
}

2、最大子段和

题目描述

输入若干个整数,有正有负,要求用动态规划算法计算最大子段和,并输出这个和。注意子段为一段连续的数,同时规定全是负数的子段其和为0。

输入

第一行为一个整数M,代表有M组测试数据。
随后每组测试数据的第一行为N,代表该组数据有N个数。(0接下来一行给出用空格隔开的这N个整数。

输出

每组测试数据输出一行,即最大子段和。

样例输入 复制

1
8
-2 10 8 -4 7 5 -29 10

样例输出 复制

26
#include <iostream>
#include <vector>
using namespace std;

int main() {
    int M;
    cin >> M;
    while (M--) {
        int N;
        cin >> N;
        vector<int> arr(N);
        for (int i = 0; i < N; i++) {
            cin >> arr[i];
        }
        int max_sum = 0, cur_sum = 0;
        bool has_positive = false;
        for (int i = 0; i < N; i++) {
            if (arr[i] > 0) {
                has_positive = true;
                break;
            }
        }
        if (!has_positive) {
            cout << 0 << endl;
            continue;
        }
        for (int i = 0; i < N; i++) {
            cur_sum += arr[i];
            if (cur_sum < 0) {
                cur_sum = 0;
            } else if (cur_sum > max_sum) {
                max_sum = cur_sum;
            }
        }
        cout << max_sum << endl;
    }
    return 0;
}

3、最大子阵型和

有一个包含正数和负数的二维数组。一个子矩阵是指在该二维数组里,任意相邻的下标是1*1或更大的子数组。一个子矩阵的和是指该子矩阵中所有元素的和。本题中,把具有最大和的子矩阵称为最大子矩阵。
例如:
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
这个数组的最大子矩阵为:
9 2
-4 1
-1 8
其和为15。

输入

输入包含多组测试数据。每组输入的第一行是一个正整数N(1<=N<=100),表示二维方阵的大小。接下来N行每行输入N个整数,表示数组元素,范围为[-127,127]。

输出

输出最大子阵和。

样例输入 复制

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

样例输出 复制

15

#include <iostream>
using namespace std;

int main() {
    int N;
    while (cin >> N) {
        int arr[N][N];
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                cin >> arr[i][j];
            }
        }
        int max_sum = -127 * N * N;
        for (int i = 0; i < N; i++) {
            int temp[N] = {0};
            for (int j = i; j < N; j++) {
                int cur_sum = 0;
                for (int k = 0; k < N; k++) {
                    temp[k] += arr[j][k];
                    cur_sum += temp[k];
                    if (cur_sum > max_sum) {
                        max_sum = cur_sum;
                    }
                    if (cur_sum < 0) {
                        cur_sum = 0;
                    }
                }
            }
        }
        cout << max_sum << endl;
    }
    return 0;
}

 4、最大上升子序列

题目描述

给出一个由n个数组成的序列A[1..n],求最长单调上升子序列(LIS)的长度。LIS即求最大的一个子序列长度m,使得a1<a2<……<am且A[a1]<A[a2]<……<A[am]。

输入

两行:

第1行:整数n (1<=n<=1000)

第2行:n个整数 (int范围内),空格隔开。

输出

一行:一个整数,即最长上升子序列长度。

样例输入 复制

10
63	11	21	36	28	20	57	37	82	4

样例输出 复制

5
#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    int arr[n], dp[n];
    for (int i = 0; i < n; i++) {
        cin >> arr[i];
        dp[i] = 1;
    }
    int max_len = 1;
    for (int i = 1; i < n; i++) {
        for (int j = 0; j < i; j++) {
            if (arr[j] < arr[i]) {
                dp[i] = max(dp[i], dp[j] + 1);
            }
        }
        max_len = max(max_len, dp[i]);
    }
    cout << max_len << endl;
    return 0;
}

该代码使用一个一维数组dp来存储以每个元素为结尾的最长上升子序列长度,初始值都为1(一个元素本身即为一个长度为1的上升子序列)。然后,双重循环枚举所有前面的元素,如果前面的元素小于当前元素,则更新以当前元素为结尾的最长上升子序列长度。最后,遍历dp数组找到最大值即可。

注意:由于本题求的是最长“上升”子序列,因此当序列中存在相同值时,不应将它们视作上升子序列的一部分。

 

5、最小乘车费用

题目描述

某条街上每一公里就有一汽车站,乘车费用如下表:

公里数

1

2

3

4

5

6

7

8

9

10

费用

12

21

31

40

49

58

69

79

90

101

而一辆汽车从不行驶超过10公里。某人想行驶n公里,假设他可以任意次换车,请你帮他找到一种乘车方案使费用最小(10公里的费用比1公里小的情况是允许的)。

输入

第一行为10个不超过100的整数,依次表示行驶1~10公里的费用,相邻两数间用空格隔开;

第二行为某人想要行驶的公里数(1000以内)。

输出

包含一个整数,表示该测试点的最小费用。

样例输入 复制

12 21 31 40 49 58 69 79 90 101 15 

样例输出 复制

147
#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    int arr[n][n];
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cin >> arr[i][j];
        }
    }
    int dp[n][n] = {0};
    dp[0][0] = arr[0][0];
    for (int i = 1; i < n; i++) {
        dp[0][i] = dp[0][i-1] + arr[0][i];
        dp[i][0] = dp[i-1][0] + arr[i][0];
    }
    for (int i = 1; i < n; i++) {
        for (int j = 1; j < n; j++) {
            dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + arr[i][j];
        }
    }
    cout << dp[n-1][n-1] << endl;
    return 0;
}

         

该代码使用一个二维数组dp来存储到达每个方格的最大数字和,其中dp[i][j]表示从左上角到第i行第j列的方格所经过的所有方格中数字和的最大值。首先,对于第一行和第一列,它们只能由上一行或上一列的方格走过来,因此它们的最大值只能是前缀数字和。然后,双重循环枚举所有方格,并使用递推式dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + arr[i][j]计算到达当前方格的最大数字和。

最终结果即为dp[n-1][n-1]

 

 

7、方格取数

题目描述

在n*n的方格阵中,从左上角出发,每次只能往正下方或右边走,找出一种路线方案,使得所经历方格中数字和最大,输出这个值。

(下图n=5)

0537539
551019238
655882899
80145068
89510410

输入

第1行:一个整数n   (1<=n<=1000)

第2-n+1行:每行n个非负整数 (整型范围)

输出

一行:一个整数

样例输入 复制

5
0	5	37	53	9
55	10	19	23	8
65	58	82	89	9
8	0	14	50	68
89	5	10	41	0

样例输出 复制

467

8、01背包 

题目描述

一个旅行者有一个最多能用M公斤的背包,现在有N件物品,
它们的重量分别是W1,W2,...,Wn,
它们的价值分别为P1,P2,...,Pn.
若每种物品只有一件求旅行者能获得最大总价值。

输入

M,N
W1,P1
W2,P2
......

输出

最大总价值。

样例输入 复制

10 4
2 1
3 3
4 5
7 9

样例输出 复制

12

9、完全背包 

题目描述

完全背包定义有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的体积是c,价值是w。求解将哪些物品装入背包可使这些物品的体积总和不超过背包容量,且价值总和最大。本题要求是背包恰好装满背包时,求出最大价值总和是多少。如果不能恰好装满背包,输出NO

输入

第一行: N 表示有多少组测试数据(N<7)。
接下来每组测试数据的第一行有两个整数M,V。 M表示物品种类的数目,V表示背包的总容量。(0<M<=2000,0<V<=50000)
接下来的M行每行有两个整数c,w分别表示每种物品的重量和价值(0<c<100000,0<w<100000)

输出

对应每组测试数据输出结果(如果能恰好装满背包,输出装满背包时背包内物品的最大价值总和。 如果不能恰好装满背包,输出NO)

样例输入 复制

2
1 5
2 2
2 5
2 2
5 1

样例输出 复制

NO
1

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值