No.3 DP动态规划(一)

    首先是数字三角形问题,由n行数字,每行由与行数对应相等数量的数字组成,求三角形从顶点到底部的一条路径使路径上三角形的数字总和最大。行数在1<=n<=100之间。三角形中每个数字都在0--99之间。下面是笔者用C语言写的代码。

#include 
#include 
#include 

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
#include
#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=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 " << data[i][j]; 
    } 
    cout << endl;
}

int main()
{
    int n;                           //有n行
    cin >> n;
    for(int i=0; i> 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] 在实现一道例题时笔者是这样写的:

#include 
#include 
#include 
#include  
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依然无法通过。

你可能感兴趣的:(ACM)