一:数塔问题
如图所示,将一些数字排成数塔的形状,其中第一层有一个数字,第二层有两个数字...第n层有n个数字。现在要全球从第一层走到第n层,每次只能走向下一层连接的两个数字,问:最后将路径上所有数字相加后得到的和最大是多少?
样例输入
5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5
样例输出
30
代码如下:
#include<iostream>
using namespace std;
int main()
{
int n;
cin>>n;
int f[501][501];
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
cin>>f[i][j];
}
}
int dp[501][501];
for(int i=1;i<=n;i++){
dp[n][i] = f[n][i];
}
for(int i=n-1;i>=1;i--){
for(int j=1;j<=i;j++){
dp[i][j] = max(dp[i+1][j],dp[i+1][j+1])+f[i][j];
}
}
cout<<dp[1][1];
return 0;
}
二:最大连续子序列和
给定一个长度为n的序列,求该序列的最大的连续子序列和。
输入
第一行一个整数n。
第2行n个整数,表示该序列。
输出
一个整数,表示该序列的最大连续子序列和。
样例输入
10
2 5 -3 4 -9 -2 6 1 -8 7
样例输出
8
代码如下:
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int dp[1001];
int main()
{
int n;
cin>>n;
int a[1001];
for(int i=0;i<n;i++){
cin>>a[i];
}
dp[0] = a[0];
for(int i=1;i<n;i++){
dp[i] = max(dp[i-1]+a[i],a[i]);
}
sort(dp,dp+n);
cout<<dp[n-1];
return 0;
}
三:单调递增最长子序列
设计一个O(n2)时间的算法,找出由n个数组成的序列的最长单调递增子序列。
输入格式:
输入有两行: 第一行:n,代表要输入的数列的个数 第二行:n个数,数字之间用空格格开
输出格式:
最长单调递增子序列的长度
输入样例:
在这里给出一组输入。例如:
5
1 3 5 2 9
输出样例:
在这里给出相应的输出。例如:
4
#include<iostream>
using namespace std;
int main()
{
int n;
cin>>n;
int a[1001];
for(int i=0;i<n;i++){
cin>>a[i];
}
int dp[1001];
int ans = 0;
for(int i=0;i<n;i++){
dp[i] = 1;
for(int j=0;j<i;j++){
if(dp[j]+1> dp[i] && a[i]>a[j]){
dp[i] = dp[j]+1;
}
}
ans = max(dp[i],ans);
}
cout<<ans;
return 0;
}
四:合并石子
代码如下:
#include<stdio.h>
#include<stdlib.h>
#define INIF 999999999
int N;
int dp[1001][1001] = { 0 };
int sum[1001][1001];
int num[1001];
void minsz() {
int i, j, k, t, len,minx;
for (i = 1; i <= N; i++) {
sum[i][i] = num[i];
for (j = i + 1; j <= N; j++) {
sum[i][j] = sum[i][j - 1] + num[j];
}
}
for(j=2;j<=N;j++){
for(i=j-1;i>0;i--){
minx=INIF;
dp[i][j]=INIF;
for(k=i;k<j;k++){
t=dp[i][k]+dp[k+1][j]+sum[i][j];
if(t<minx) minx = t;
}
dp[i][j]=minx;
}
}
printf("%d\n", dp[1][N]);
}
int main(void) {
int i;
scanf("%d", &N);
for (i = 1; i <= N; i++) {
scanf("%d", &num[i]);
}
minsz();
return 0;
}