第五章 动态规划

01-背包
f[0] = 0;
for(int i = 1; i <= n; i++)
	for(int j = m; j >= v[i]; j--)             
		f[j] = max(f[j], f[j-v[i]] + w[i]);
完全背包
for(int i = 1; i <= n; i++)
    for(int j = v[i]; j <= m; j++)
        f[j] = max(f[j], f[j-v[i]] + w[i]);
多重背包
for(int i = 1; i <= n; i++)
    for(int j = m; j >= v[i]; j--)
        for(int k = 1; k <= s[i]; k++){	// s[i]第i个物品的数量
            if(k * v[i] > j) break;
            f[j] = max(f[j], f[j-k*v[i]] + k*w[i]);
        }       
分组背包

每组物品有若干个,同一组内的物品最多只能选一个。

for(int i = 0; i < n; i++){
  	int s;
    cin >> s;
    for(int j = 0; j < s; j++)
        cin >> v[j] >> w[j];
    for(int j = m; ~j; j--){
        for(int k = 0; k < s; k++){
            if(j < v[k]) break;
            f[j] = max(f[j], f[j-v[k]] + w[k]);
        }
    }      
}
数字三角形
// 最底层初始化
for(int i = 1; i <= n; i++)
    f[n][i] = d[n][i];

// 从倒数第二层开始计算
for(int i = n-1; i >= 1; i--)
    for(int j = 1; j <= i; j++)
        f[i][j] = max(f[i+1][j], f[i+1][j+1]) + d[i][j];
最长上升子序列 LIS
f[0] = d[0];
for(int i = 1; i < n; i++)
    f[i] = max(d[i], f[i-1] + d[i]);

// LIS
//  f[i]:所有以第i个数结尾的上升子序列的最大值
for(int i = 0; i < n; i++){
   f[i] = 1;   // f[i]至少有a[i]这个数
    for(int j = 0; j < n; j++){
        if(a[i] >= a[j]) 
            f[i] = max(f[i], f[j] + 1);
    }
}
最长公共子序列 LCS
/*
    f[i, j] 在字符串A的前i个字母中出现,且在字符串B的前j个字母中出现的子序列长度
    若a[i] == b[j] f[i,j] = f[i-1, j-1] + 1
    若a[i] != b[j] f[i,j] = max(f[i, j-1], f[i-1, j])
*/
for(int i = 1; i <= n; i++)
   for(int j = 1; j <= m; j++){
        if(a[i] == b[j]) f[i][j] = f[i-1][j-1] + 1;
        else f[i][j] = max(f[i][j-1], f[i-1][j]);
    }
最短编辑距离
int minDistance(string word1, string word2) {
    int f[510][510];
    f[0][0] = 0;
    int n = word1.length(), m = word2.length();
    
    // f[i][0] =  f[i-1][0] + 1;
    for(int i = 1; i <= n; i++) f[i][0] = i ;       
    for(int i = 1; i <= m; i++) f[0][i] = i;
       
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            f[i][j] = min(f[i][j-1] + 1, f[i-1][j] + 1);    // 删除和增加比较
            if(word1[i-1] == word2[j-1]) f[i][j] = min(f[i][j], f[i-1][j-1]);   // 如果相等,就不需要编辑
            else f[i][j] = min(f[i][j], f[i-1][j-1] + 1);                  
        }
    }
    return f[n][m];         
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值