首先是数字三角形问题,由n行数字,每行由与行数对应相等数量的数字组成,求三角形从顶点到底部的一条路径使路径上三角形的数字总和最大。行数在1<=n<=100之间。三角形中每个数字都在0--99之间。下面是笔者用C语言写的代码。
#include <iostream>
#include <cstdio>
#include <algorithm>
const int maxn=105;
int col[maxn][maxn];
int MAX(int A,int B)
{
int t;
if(A>=B)
t=A;
else
t=B;
return t;
}
int main()
{
int n,i,j,m;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
for(j=1;j<=i;j++)
{
scanf("%d",&col[i][j]);
}
}
for(i=n;i>0;i--)
{
for(j=1;j<=i;j++)
{m=MAX(col[i][j],col[i][j+1]);
col[i-1][j]=col[i-1][j]+m;}
}
printf("%d",col[1][1]);
}
(col row)需要注意的是在定义数组时,并没有从0开始,而是从一开始。这个题是一道简单的动态规划题,在这里,如果从顶点顺序搜索查找,并不是一件容易的事,从底部则不同,从底部向上,可以排除掉较小的情况。数据如下:
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
30
#include<iostream>
#include<cmath>
#define MAX 1000
using namespace std;
int data[MAX][MAX]; //储存原始数据
int dp[MAX][MAX]; //储存刷新后的数据
int tower_walk(int n)
{
//dp初始化
for(int i=0; i<n; i++)
dp[n-1][i] = data[n-1][i];
int temp_max; //取最大值
for(int i=n-2; i>=0; i--)
for(int j=0; j<=i; j++)
{
temp_max = max(dp[i+1][j],dp[i+1][j+1]);
dp[i][j] = temp_max + data[i][j];
}
}
//打印和最大路径
int print(int n)
{
cout << "最大路径和:" << dp[0][0] << endl;
int node_value;
//首先输出塔顶元素
cout << "最大路径:" << data[0][0];
int j=0;
for(int i=0; i<n; i++)
{
if(node_value == dp[i][j+1])
j++;
cout << " -> " << data[i][j];
}
cout << endl;
}
int main()
{
int n; //有n行
cin >> n;
for(int i=0; i<n; i++)
for(int j=0; j<=i; j++)
cin >> data[i][j];
tower_walk(n);
cout << dp[0][0] << endl; //最大值储存在dp[0][0]中
return 0;
}
上式为网上C++算法,笔者并没有感觉特别好。
第二,最长上升子序列(LIS)的查找,最长公共子序列(LCS)的查找,最长公共上升子序列的查找。
关于最长公共上升子区间的查找,笔者有一种想法,但是被排除了:
分别求出各自的最长上升子区间再求公共部分(贪心算法)但是被排除了,例子如下:
11 12 13 4 5 6 7 8 9 10 14 15 16 17 18 19
11 14 15 4 5 6 7 8 9 10 16 17 18 19 20 21
在这种情况下不成立。
要求最长上升子序列利用DP方程,F[i] 表示为序列A[1..i]中的一个最长递增子序列中的长度(以A[i]结尾)状态转移方程为:F[i]=Max{F[j]+1}
j < i
A[j]<A[i]
在实现一道例题时笔者是这样写的:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
using namespace std;
const int maxn=300;
char A[maxn],B[maxn];
int lena,lenb;
int LCS(int i,int j)
{
if(i>=lena || j>=lenb)
return 0;
if(A[i]==B[j])
return 1+LCS(i+1,j+1);
else
return LCS(i+1,j)>LCS(i,j+1)? LCS(i+1,j):LCS(i,j+1);
}
int main()
{
int i,j,d;
while(~scanf("%s%s",A,B))
{lena=strlen(A);
lenb=strlen(B);
printf("%d\n", LCS(0,0) ); }
return 0;
}
但是oj显示TL,笔者将数组压到200依然无法通过。