这个时候边界不是很好确定,所以可以使用记忆化搜索比较容易一点
需要注意的一点是:
更新状态的时候,一定要使用dp(x),而不是d[x]
#include<cstdio> #include<algorithm> using namespace std; int A[] = {0,1,5,2,6,8,7}; int B[] = {0,2,3,5,6,9,8,4}; const int maxn = 10; int d[maxn][maxn];//i,j代表A1~i与B1~j的最长公共子序列 int vis[maxn][maxn]; //如果a[i] == b[j] 那么d[i][j] = d[i - 1][j - 1] + 1; //如果a[i] != b[j] 那么d[i][j] = max(d[i - 1][j],d[i][j - 1]) //但是需要注意边界,即i或者j上面有1的就是边界 //d[1][1] = 0 / 1 //记忆化搜索更容易理解,适用于不容易求边界的情况 int dp_LCS(int i,int j) { if(vis[i][j]) return d[i][j]; vis[i][j] = 1; if(i == 0 || j == 0) { d[i][j] = 0; return 0; } if(A[i] == B[j]) { d[i][j] = dp_LCS(i - 1,j - 1) + 1; return d[i][j]; } if(A[i] != B[j]) { d[i][j] = max(dp_LCS(i - 1,j),dp_LCS(i,j - 1)); return d[i][j]; } } // int d_LIS[maxn];//d[i]表示从1~i的最长上升子序列,d[i] = max{d[j]|j < i && A[j] < A[i]} int vis_LIS[maxn]; int dp_LIS(int i) { if(vis_LIS[i]) return d_LIS[i]; vis_LIS[i] = 1; d_LIS[i] = 0; for(int j = 1;j < i;j++) { if(A[j] < A[i]) { d_LIS[i] = max(d_LIS[i],dp_LIS(j)); } } d_LIS[i] += 1; return d_LIS[i]; } int main() { memset(vis,0,sizeof(vis)); memset(vis_LIS,0,sizeof(vis_LIS)); dp_LCS(6,7); dp_LIS(6); return 0; }
原文地址:https://www.cnblogs.com/TorettoRui/p/10483023.html
时间: 2024-10-11 21:26:02