f[i][j]存储第i行第j个点的数值,令dp[i][j]表示第i行第j个数字出发的到达最底层的所有路径中能得到的最大和。i,j都从1开始
显然: dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+f[i][j]
得到状态转移方程,而最后一层dp值总是等于元素本身。
即:dp[n][j]==f[n][j](1<=j<=n) 把这种可以直接确定其结果的部分称为边界
而动规的递推写法总是从这些边界出发,通过状态转移方程扩散到整个dp数组。
从最底层各位置的dp值开始,不断往上求出每一层各位置的dp值,最后就会得到最终结果dp[1][1]
//录入边界
for(int j=1;j<=n;j++){
dp[n][j]=f[n][j];
}
//状态转移 从n-1层不断往上计算出dp[i][j]
for(int i=n-1;i>=1;i--){
for(int j=1;j<=i;j++){
dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+f[i][j];
//每次通过i+1层求第i层 且每次i+1都先求出来了
}
}
// a数组从下标0开始
dp[0] = a[0];
int maxn = a[0];
for(int i = 1; i < n; i++) {
dp[i] = max(a[i], dp[i-1]+a[i]);
maxn = max(dp[i], maxn);
}
printf("%d", maxn);
int ans = 0;
for(int i = 0; i < n; i++) {
for(int j = 1; j < i; j++) {
if(a[i] >= a[j])
dp[i] = max(dp[i], dp[j] + 1);
}
ans = max(dp[i], ans);
}
printf("%d", ans);
dp[i][j]
表示A的第 i 位之前和B的第 j 位之前的这两个序列的LCS最长公共子序列的长度(下标从1开始),那么dp[lena][lenb]
即为所求dp[i][j] = dp[i-1][j-1] + 1
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
dp[i][0] = dp[0][j] = 0
(0 <= i <= lena, 1 <= j <= lenb)
char a[100], b[100];
scanf("%s", a+1);
scanf("%s", b+1);
int lena = strlen(a + 1), lenb = strlen(b + 1);
for(int i = 0; i <= lena; i++) dp[i][0] = 0;
for(int j = 0; j <= lenb; j++) dp[0][j] = 0;
for(int i = 1; i <= lena; i++) {
for(int j = 1; j <= lenb; j++) {
if(a[i] == b[j])
dp[i][j] = dp[i-1][j-1] + 1;//若可以产生重复元素
// dp[i][j] =max(dp[i-1][j], dp[i][j-1]) + 1;
else
p[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
printf("%d", dp[lena][lenb]);
dp[i][j]
表示 s[i] 到 s[j] 所表示的字串是否是回文字串,值只有0和1dp[i][i] = 1, dp[i][i+1] = (s[i] == s[i+1]) ? 1 : 0
,然后长度L从3到len,满足的最大长度L即为所求的ans值dp[i][j] = dp[i+1][j-1]
dp[i][j] = 0
dp[i][j]
的时候dp[i+1][j-1]
已经被计算过。因此不妨考虑按照字串的长度和子串的初试位置进行枚举,即第一遍将长度为3的子串的dp的值全部求出,第二遍通过第一遍结果计算出长度为4的子串的dp的值…这样就可以避免状态无法转移的问题int len = s.length();
//先把1和2长度的都初始化了
int ans = 1;
for(int i = 0; i < len; i++) {
dp[i][i] = 1;
if(i < len - 1 && s[i] == s[i+1]) {
dp[i][i+1] = 1;
ans = 2;
}
}
//状态转移方程
for(int L = 3; L <= len; L++) {
for(int i = 0; i + L - 1 < len; i++) {
int j = i + L - 1;
if(s[i] == s[j] && dp[i+1][j-1] == 1) {
dp[i][j] = 1;
ans = L;
}
}
}
printf("%d", ans);
dp[i][j]
表示前i件物品恰好装入容量为j的背包所能获得的最大价值
dp[i][j] = dp[i-1][j]
dp[i-1][j-w[i]] + c[i]
dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+c[i]);
for(int i = 1; i <= n; i++) {
for(int j = 1, j <= v; j++)
if(j - w[i] >= 0)
dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + c[i]);
else
dp[i][j] = dp[i-1][j];
}
for(int i = 1; i <= n; i++) {
for(int j = v; j >= w[i]; j--)
dp[v] = max(dp[v], dp[v-w[i]] + c[i]);
}