现在的位置: 首页 > 综合 > 正文

动态规划解各种子序列问题

2018年01月17日 ⁄ 综合 ⁄ 共 2751字 ⁄ 字号 评论关闭

1、最长公共序列(LCS)

#include <iostream>
#include <algorithm>
using namespace std;

#define UP 		1
#define LEFT 	2
#define SLOPE	3

int dp[50][50];
int road[50][50];

char a[] = "ALGORITHM";
char b[] = "ALTRUISTIC";

void print(int x, int y)
{
	if(x < 1 || y  < 1)
		return;
	if(road[x][y] == SLOPE)
	{
		print(x-1, y-1);
		cout << a[x-1] << " ";
	}
	else if(road[x][y] == LEFT)
		print(x, y-1);
	else
		print(x-1, y);
}

int lcs()
{
	int len1 = strlen(a), len2 = strlen(b);
	dp[0][0] = 0;
	for(int i = 1; i <= len1; ++i)
		dp[i][0] = 0;
	for(int i = 1; i <= len2; ++i)
		dp[0][i] = 0;
	for(int i = 1; i <= len1; ++i)
	{
		for(int j = 1; j <= len2; ++j)
		{
			if(a[i-1] == b[j-1])
			{
				dp[i][j] = dp[i-1][j-1] + 1;
				road[i][j] = SLOPE;
			}
			else
			{
				dp[i][j] = max(dp[i-1][j], dp[i][j-1]);	
				road[i][j] = dp[i-1][j] > dp[i][j-1] ? UP : LEFT;			
			}
		}
	}
	return dp[len1][len2];
}

int main(void)
{	
	memset(dp, 0, sizeof(dp));
	memset(road, 0, sizeof(road));
	
	cout << lcs() << endl;
	print(strlen(a), strlen(b));
	
	return 0;
}

2、最大子序列和

#include <iostream>
using namespace std;

int a[] = {
	//-2, 11, -4, 13, -5, -2
	-6, 2, 4, -7, 5, 3, 2, -1, 6, -9, 10, -2
};

int dp[30], x = -1;

int lss()
{
	dp[0] = a[0];
	int len = sizeof(a) / sizeof(*a), ret = -255;
	for(int i = 1; i < len; ++i)
	{
		dp[i] = dp[i-1] > 0 ? dp[i-1]+a[i] : a[i];	
		if(ret < dp[i])
		{
			ret = dp[i];
			x = i;
		}		
	}	
	return ret;
}

void suffix()
{
	int i;
	for(i = x; i >= 0; --i)
	{
		if(dp[i] < 0)
			break;
	}
	cout << "具有最大和子序列的下标位置为:" << i+1 << " " << x << endl;
}

int main(void)
{
	memset(dp, 0, sizeof(dp));
	cout << lss() << endl;	
	suffix();
	
	return 0;
}

3、最长递增子序列长度(LIS)

#include <iostream>
using namespace std;

int a[] = {
	1, -1, 2, -3, 4, -5, 6, -7
};

int dp[25];

int lis()
{
	int len = sizeof(a) / sizeof(*a), ret = -1;
	for(int i = 0; i < len; ++i)
	{
		dp[i] = 1;
		for(int j = 0; j < i; ++j)
		{
			if(a[i] > a[j] && dp[j] + 1 > dp[i])
				dp[i] = dp[j] + 1;
		}
		if(ret < dp[i])
			ret = dp[i];
	}
	return ret;
}

int main(void)
{
	memset(dp, 0, sizeof(dp));
	cout << lis() << endl;
	
	return 0;
}

4、最长连续公共子序列长度(最长公共子串)

#include <iostream>
using namespace std;

int opt[65535];

int max(int a, int b)
{
	return a > b ? a : b;
}

int maxSubLen(const char *src, const char *trg)
{
	int len1 = strlen(src);
	int len2 = strlen(trg);
		int largest = -1;
	for(int j = 0; j < len2; ++j)	
	{
		for(int i = len1 - 1; i >= 0; --i)
		{
			if(src[i] == trg[j])
			{
				if(i == 0)
					opt[i] = 1;
				else
					opt[i] = opt[i-1] + 1;

				if(largest < opt[i])
						largest = opt[i];
			}
			else
				opt[i] = 0;
		}
	}
	
	return largest;
}


int main(void)
{
	char text[] = "acbac";
	char query[] = "acaccbabb";
	memset(opt, 0, sizeof(opt));
	
	cout << maxSubLen(query, text) << endl;
	
	return 0;
}


5、矩阵最大子矩阵和

#include <iostream>
using namespace std;

const int m = 3, n = 3;

int a[10][10] = {
	{7, -8, 9},
	{-4, 5, 6},
	{1, 2, -3}
};

int b[10];
int dp[10];
int start, end;
int lss()
{
	dp[0] = b[0];
	int res = dp[0];
	start = 0, end = 0;
	for(int i = 1; i < n; ++i)
	{
	//	dp[i] = dp[i-1] > 0 ? dp[i-1] + b[i] : b[i];
		if(dp[i-1] < 0)
		{
			start = i;
			dp[i] = b[i];
		}
		else
			dp[i] = dp[i-1] + b[i];
	//	res = dp[i] > res ? dp[i] : res;
		if(dp[i] > res)
		{
			res = dp[i];
			end = i;
		}
	}
	return res;
}

int main(void)
{
	int x1 = 0, x2 = 0, y1 = 0, y2 = 0;
	int maxv = a[x1][y1];
	
	for(int l1 = 0; l1 < m; ++l1)
	{
		for(int l2 = l1+1; l2 < m; ++l2)
		{
			memset(b, 0, sizeof(b));
			int i;
			for(i = l1; i < l2; ++i)
			{
				for(int j = 0; j < n; ++j)
				{
					b[j] += a[i][j];
				}
			}
			int t = lss();
			if(maxv < t)
			{
				maxv = t;
				x1 = l1; x2 = l2;	
				y1 = start; y2 = end;
			}
		}
	}
	
	cout << "第" << x1+1 << "行到" << x2 + 1 << "行,第" << y1+1 << "列到第" << y2+1 << "列构成的子矩阵和最大,为:" << maxv << endl;
	return 0;
}

抱歉!评论已关闭.