2021-04-17

线性dp给我的启发

最近一周做dp的题,打心底来说,思考量很大,真的不容易找出来状态转移方程。做题目前需要题解辅助 ,可能是因为做题量太少的问题 ,才十几个简单的线性dp题就想做题行云流水是不太现实,目前要做的首要目标就是多刷题,可是想了半天不会做啊 这就很难受了, 还得需要讨论和搜题解,反正就做吧 多总结见的多了 自然就慢慢开窍了吧

题目总结

以下给出我做出的让我对dp有点感觉的题目;

## worm:

自从见识了平安夜苹果的涨价后,Lele就在他家门口水平种了一排苹果树,共有N棵。 

每过1分钟,毛毛虫会随机从一棵树爬到相邻的一棵树上。 

比如刚开始毛毛虫在第2棵树上,过1分钟后,毛毛虫可能会在第1棵树上或者第3棵树上。如果刚开始时毛毛虫在第1棵树上,过1分钟以后,毛毛虫一定会在第2棵树上。 

现在告诉你苹果树的数目N,以及毛毛刚开始所在的位置P,请问,在M分钟后,毛毛虫到达第T棵树,一共有多少种行走方案数。



            //n是大树的数量;s是初始位置;e是结束位置 x是用的时间

            memset(a,0,sizeof(a));
               a[0][s]=1;

            for(int i=1;i<=x;i++)  //i是当前的时间  j是当前的位置
                  for(int j=1;j<=n;j++)
                  a[i][j]=a[i-1][j+1]+a[i-1][j-1];
                  //当前的时间和位置 只能从前一秒: j-1位置 或者j+1位置过来
                  //除了初始位置是1  其他都是零


                  cout<<a[x][e]<<endl;

这个题 一开始我是没有用dp
想着 开始是s 结束是e 那么abs(e-s)就是他俩之间的距离 ,虫子一分钟一个距离 一共m个距离 可以左可以右。所以相当于有i个1,有j个-1 。i+j=m;abs(i-j)=abs(e-s),m每次增加一或者减一 循环p=m次 ;当p=0时;
m=abs(e-s)有几种情况 ;后来越想越复杂;就开始转换思路;尝试用dp;
去想状态转移方程;
动态转移方程:dp[i][j]=dp[i-1][j-1]+dp[i-1][j+1]

1.i表示时间

2.j表示位置

则i时间,j位置只能从i-1时间j+1位置或j-1位置走来

一开始把p位置赋值为1,其他全为0,这样一步步时间往上加就得到了结果;
总结:
这个是从前往后推;知道的已知条件就是初始位置 所以就从前向后 ,有的题是从后向前,因为已知条件是结束位置;并且 这个题是按照空间位置和时间来划分状态 确定子问题的;dp数组的两个下标都是有意义的;

Jumping Cows

  给你n个药的序列,牛从时间1开始吃药,在奇数时间吃药可以增加弹跳力,
  在偶数时间吃药则会减少弹跳力。在某一时间,可以跳过一些药,但一旦吃过
  某种药,你就不能在选前面的药了。问某一个吃药的序列,使牛最终的弹跳力
  最大。
dp[0][0]=0;
        dp[0][1]=0;
        for(i=1;i<=n;i++)
        {
            cin>>t;
            dp[i][0]=max(dp[i-1][0],dp[i-1][1]-t);
            dp[i][1]=max(dp[i-1][1],dp[i-1][0]+t);
        }
        cout<<max(dp[n][0],dp[n][1])<<endl;

这个题我刚开始的思路是这样的;给出一个数组;从某个元素开始 往后取元素;去除的元素组成的新数组与原来数组的顺序不变;但是新数组奇数元素为负数,偶数为证 ,想着让奇数子数组最大,偶数子数组最小,所以用了贪心却没有ac
我就开始用dp
dp[i][0] 为 当拿到第i个药时,之前已经拿了奇数个药的最大弹跳力。

dp[i][1] 为 当拿到第i个药时,之前已经拿了偶数个药的最大弹跳力。

dp[i][0] = max(dp[i-1][0], dp[i-1][1]- v[i]);
dp[i][1] = max(dp[i-1][1], dp[i-1][0]+v[i])
每次都是存入以第i个药结束的最大弹跳力,但是i分奇数偶数,所以0列存i为偶数 1列存储i为奇数;所以 最大值就在dp【n】【0】和dp【n】【1】之间;

 Super Jumping! Jumping! Jumping! 

实际上就是求最大递增子列的和;
这个题是我做完最大递增子链后来做的;
我一开始以为这两个题好像一样;后来一分析,本体是子列 不仅要顺序还要连续;

dp[0] = d[0];
		for (i = 1; i < n; i++)
		{
			dp[i] = d[i];
			for (j = 0; j < i; j ++)
				if (d[j] < d[i] && dp[j] + d[i] > dp[i])
					dp[i] = d[i] + dp[j];
		} 
		dp【i】表示是以i结尾的最大递增子列和;dp【i】满足  
		a【 i】>a【j】并且要和dp【j】+a【i】联合,这样子保证连续;
		     

这个题还是比较简单的 只有一个下标来确定状态 划分子问题;也是从前向后推;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值