经典动态规划的迭代条件

1、硬币找零:

if(j<penny[i])
    dp[i][j] = dp[i-1][j];
else
    dp[i][j] = dp[i-1][j]+dp[i][j-penny[i]];
//其中,i代表硬币种类,j代表目标钱数,dp[i][j]表示由i种硬币凑成钱数j的方法个数。

2、经典的LIS(即最长上升子序列)问题:

int temp=0;
for(int j=0;j<i;j++)
{
    if(A[i]>A[j])
        temp = temp>dp[j]?temp:dp[j];
}
dp[i] = temp+1;
//dp[i]表示最后一个字符为i的最长上升序列的长度。思路:找到i前面,比A[i]小的字符中最长上升序列的长度然后加1

3、两个字符串A、B的最长公共子序列的长度

int res = max(dp[i-1][j],dp[i][j-1]);
if(A[i] == B[j])
    res = max(dp[i-1][j-1]+1,res);
dp[i][j] = res;
//dp[i][j]表示A[0-i]与B[0-j]的最长公共子序列的长度。

4、0-1背包问题

if(j>=w[i])
    dp[i][j] = max(dp[i-1][j],dp[i-1][j-w[i]]+v[i]);
else
    dp[i][j] = dp[i-1][j];
//i表示i个物品,j表示背包承重,w[i]表示第i个物品重量,v[i]表示第i个物品价值。
//完全背包以及0-1背包的改进,可以参考http://blog.csdn.net/kangroger/article/details/38864689

5、对于两个字符串A和B,我们需要进行插入、删除和修改操作将A串变为B串,定义c0,c1,c2分别为三种操作的代价,请设计一个高效算法,求出将A串变为B串所需要的最少代价。

if(A[i-1] == B[j-1])
    dp[i][j] = min(dp[i-1][j-1],min(dp[i][j-1]+c0,dp[i-1][j]+c1));
else
    dp[i][j] = min(dp[i-1][j-1]+c2,min(dp[i][j-1]+c0,dp[i-1][j]+c1));

6、word break

for(int j=0;j<i;j++)
{
    if(dp[j]&&dict.find(s.substr(j,i-j)) != dict.end())
    {
        dp[i] = true;
        break;
    }
}
//思路:dp[i]表示以s[i-1]结尾的字符串能否被分割,需要从0-(i-1)遍历,查看dp[j]是否为true同时s[j-(i-1)]是否在dict中,若有一个满足则dp[i]为true并跳出循环。
//注意substr和substring的区别,substrpos,n)表示从下标pos开始n个字符,substring(pos1,pos2)表示从下标pos1到下标pos2.

个人总结:
dp分为两种:一种是只与有限个状态有关,一般为二维dp,与dp[i-1][j]、dp[i][j-1]、dp[i-1][j-1]有关,如1、3、4、5。
另一种是与前i-1个状态都有关,一般为一维dp,如2、6。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值