动态规划(dp)入门:杭电OJ1087

最近在碰到一个这样的题目,但是这个我认为就是动态规划里面比较难的题目了。

动态规划,其实我认为其实就是类似于高中的数列里面的递推公式,只不过是在递推的过程中增加了一些判断条件(就像本题)。

解决动态规划的问题的步骤大致可以分为三种:

一,理解dp的含义

二,推理出递推公式

三,找出初始值。

想要具体的了解这三个步骤的含义,可以参考这篇博客

下面来分析本题:

一,设置dp[i],这里一定要理解,dp[i]是指从原点到第i个点的最大的分数。本题中的对dp的初始化在代码中有相应的注释

二,推理出递推公式,本题中的推理公式就需要有一定的判断条件。判断条件就是if(chessmen(j)<chessmen(i))  之后才能执行  dp[i] = max(dp[i],dp[j] + chessmen[i]),解释一下这个含义,dp[i]原本代表的是到 i 的位置已知的所能得到的最大的分数,dp[j] + chessmen[i]的意思则是在位置 j 到 i 的位置的所添加新的分数,从而找到这个最大的分数。最终循环完了之后就可以找到这个最大的分数

三,找出初始值。本题中的初始值不必找,因为这个在一开始我就定义了dp[i]的初始值,就不必再找初始值。

下面来看代码,代码中有更有详细的注释

#include<iostream>
#include<algorithm> 
#include<cstring>
using namespace std;
const int MAXN = 1005;
int main()
{
	int N;
	int chessmen[MAXN];
	int dp[MAXN];//动态规划,这个dp[i]代表的是从原点到第i个的最大值。
	//dp[i] = max(dp[i],.dp[j]+chessmen[i]);//第一个dp[i]的含义是从原点直接到达这个点所得到的分数
	while(1)
	{
		cin>>N;
		if(!N)
			break;
		memset(dp,0,sizeof(dp));//全部初始化
		for(int i =1;i<=N;i++)
		{
			cin>>dp[i];// dp[i]一开始代表的是从原点直接跳到这个位置所得到的分数 
			chessmen[i] = dp[i];
		 } 
		 int maxmum = dp[0]; // = 0
		 for(int  i = 1;i<=N;i++)
		 {
		 	for(int j = 1;j<i;j++)//这里的不能是<=  因为不能从自己跳到自己 
		 	if(chessmen[j]<chessmen[i])
		 		dp[i] = max(dp[i],dp[j]+chessmen[i]);
			if(maxmum<dp[i])
			maxmum = dp[i];
		 }
		 cout<<maxmum<<endl;
	 } 
	 return 0;
}

 另外再附上杭电OJ上的另外一题:编号2062

 这个题目的三个含义读者可以自己先找找

#include <stdio.h>

int main() {
    long long num_perGroup[21],m;//num_perGroup:下标i中每组的个数,比如num_perGroup[3]=5
    int n,i,group,print_num[21];//print_num是根据计算出的位置打印数
    num_perGroup[1] = 1;
    for (i = 2; i <= 20 ; ++i)//根据前文推理的公式,初始化每组个数
        num_perGroup[i] = (i-1) * num_perGroup[i - 1] + 1;
    while (scanf("%d%lld",&n,&m)!=EOF){
        for (i = 1; i <=20 ; ++i)//初始化打印数,打印第i个位置就是i,随着输出进行,其会发生变化
            print_num[i] = i;
        while (m){//当m更新为0时就不需要再打印即退出
            group = (m-1)/num_perGroup[n] + 1;//计算当前打印数,即计算为第几组,
            printf("%d",print_num[group]);//根据组号打印
            for (i = group; i < 20 ; ++i)//打印后,把打印完的覆盖,之后不会在打印
                print_num[i] = print_num[i+1];
            m = m % num_perGroup[n];//计算在组内的位置
            if(m==0)//在最后一个位置
                m = num_perGroup[n];
            m--;//去除第一个不要任何数跟着的情况比如{3}{2}{1},这在后续迭代中很重要,否则会计算组数错误。
            n--;//打印出了一个,因此n要减去一个
            if(m)//判断是否打印完
                printf(" ");
            else
                printf("\n");
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值