Two HDU - 5791 dp

题解

题目大意 给你两个数列让你求公共子序列数量

使用动态规划求解 d[i][j]表示a数列的前i个长度和b数列的前j个长度的公共子序列的数量 遍历a和b的每个位置
如果当前位置不相等则等于 a长度-1的+b长度-1的答案再减去重复的部分a和b长度-1的答案
d[i][j] = d[i - 1][j] + d[i][j - 1] - d[i - 1][j - 1]
如果当前位置相等则等于 不相等的答案+a和b长度都减一的答案(在前面追加当前字符)+单独的当前字符的一个答案
d[i][j] = d[i - 1][j] + d[i][j - 1] - d[i - 1][j - 1] + d[i - 1][j - 1] + 1
d[i - 1][j - 1]可以约掉

AC代码

#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int MAXN = 1e3 + 10;
ll d[MAXN][MAXN]; //a前i位 b前j位
int a[MAXN], b[MAXN];

int main()
{
#ifdef LOCAL
	freopen("C:/input.txt", "r", stdin);
#endif
	int N, M;
	while (cin >> N >> M)
	{
		memset(d, 0, sizeof(d));
		for (int i = 1; i <= N; i++)
			scanf("%d", &a[i]);
		for (int i = 1; i <= M; i++)
			scanf("%d", &b[i]);
		for (int i = 1; i <= N; i++)
			for (int j = 1; j <= M; j++)
			{
				if (a[i] == b[j]) //相同则等于不相同的加上a和b都减1后面追加当前 和当前相同的1贡献 化简得式子
					d[i][j] = d[i - 1][j] + d[i][j - 1] + 1 % MOD;
				else //如果当前位不同则等于a长度减1加b长度减1并减去长度都减1的重复部分
					d[i][j] = (d[i - 1][j] + d[i][j - 1] - d[i - 1][j - 1] + MOD) % MOD;
			}
		cout << d[N][M] << endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/CaprYang/article/details/85103047