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)
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 |
输入
第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