LCS(最长公共子序列)
求长度:
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(a[i] == b[i]){//数组下标从1 开始而不是从0开始
dp[i][j] = dp[i-1][j-1] + 1;
}else{
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
}
题目:
完整代码:
#include<stdio.h>
#include<string.h>
#define MAX 1000
int max(int x, int y){
return x > y ? x : y;
}
int main(){
char a[MAX], b[MAX];
fgets(a, sizeof(a), stdin);
fgets(b, sizeof(b), stdin);
int n = strlen(a) - 1;//为了去掉字符串末尾的换行符 ‘\n’,并存储字符串的长度减一。
int m = strlen(b) - 1;
int dp[n+1][m+1];
memset(dp, 0, sizeof(dp));
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(a[i-1] == b[j-1]){
dp[i][j] = dp[i-1][j-1] + 1;
}else{
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
}
printf("%d", dp[n][m]);
return 0;
}
求序列:
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
if(a[i-1] == b[i-1]){
dp[i][j] = dp[i-1][j-1];
}else{
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
}//长度求出来了,dp[][]二维数组也定义好了
int x = n, y = m;
while(x && y ){
if(a[x] == b[y]){
subsequence[max] = a[x];
x--, y--;
}else{
if(dp[x-1][y] > dp[x][y-1]){
x--;
}else{
y--;
}
}
LIS(最长上升子序列)
for(int i = 1; i <= n; i++){
dp[i] = 1;
for(int j = 1; j < i; j++){
if(a[j] < a[i]){
dp[i] = max(dp[i], dp[j] + 1);
}
}
}
线性DP(例题核心代码呈现)
金字塔三角形:
题目概述:
核心代码:
for(int i = n; i >= 1 ; i--){
for(int j = 1; j <= i; j++){
dp[i][j] = a[i][j] + max(dp[i+1][j], dp[i+1][j+1]);
}
}
printf("%d", &dp[1][1]);
爬楼梯问题:
题目:
核心代码:
dp[0] = 0;
dp[1] = 1;
dp[2] = 2;
for(int i = 1; i <= n; i++){
dp[i] = dp[i-1] + dp[i-2];
}
printf("%d", dp[n]);
ps:
注意dp数组的类型,如果算出来的数字过大,则需要定义long long 类型:
long long dp[n+1];
小进阶:
请看题目:
答案的核心代码:
int main(){
int n, m, x;
for(int i = 1; i <= m; i++){
scanf("%d", &x);
broken[x] = 1;
}
dp[0] = 1;
if(!broken[1])dp[1] = 1;
for(int i = 2; i <= n; i++){
if(broken[i] = 1)continue;
dp[i] = dp[i-1] + dp[i-2];
}
printf("%d", dp[n]);
return 0;
}
安全序列:
题目:
核心代码:
dp[油桶数][位置] 方案数
// 初始化第一列,表示使用 0 个油桶,在任意位置的方案数都为 1
for(int i = 0; i <= n; i++){
dp[i][0] = 1;
}
// 依次计算每个位置的方案数
for(int i = 1; i <= n; i++){
for(int j = 1; j <= N; j++){
// 对于每个位置,可以选择不使用当前油桶(i-1)或者使用当前油桶(i-1)
// 如果当前位置与上一个位置之间的距离大于等于 k,则可以使用上一个位置的方案数
dp[i][j] = dp[i-1][j] + ((j - k >= 0) ? dp[i-1][j-k] : 0);
}
}
printf("%d", dp[n][N]);