4月17日一周学习总结

4月17日一周学习总结

简单dp问题

这周依然是简单dp问题,虽然称为简单dp,可出的题型却多种多样,但都是以寻找动态转移方程为主,个人认为因为动态规划是对全局的判断,所以当前情况一定与上一步存在某种联系,然后可以当前的情况列动态转移方程,用之前的情况来表示出当前可能的情况,然后遍历所有可能的情况。
个人觉得比较经典的一道,虫子爬树:有一排树,一只虫子每分钟可以爬到邻近的树上,给出虫子最初的位置,问当虫子到特定的时间到特定的树有多少种情况。

int dp[205][205]={0}; 
		dp[0][100+p]=1; 
		for(i=1;i<=m;i++)
		{
			for(j=101;j<=100+n;j++)
			{
				dp[i][j]=dp[i-1][j-1]+dp[i-1][j+1];
			}
		}

这道题的动态转移方程就是当前状态一定是左边的状态加上右边的状态,而第一层循环则是时间的循环,从1到m分钟,设置转移方程时一定要注意一点,对第一次的状态进行初始化,这样才能保证该接下来的情况有原始数据可循。
类似的还有买票这一道题:一组数据,包括了一个人买票和与上一个人一起买票的价格,求最小价格。

for(int i=2;i<=n;i++)
		dp[i]=min(dp[i-1]+a[i],dp[i-2]+b[i-1]);

一个人买票只有两种情况,要么自己买,要么两个人一起买,从第一个开始遍历,同时记录当前上个人一个人买票和不买票的情况,然后当前人比较一个人买票和两个人买票地情况,找较小值。这类题都是先找对应关系然后写出动态转移方程,根据方程遍历所有情况。
然后是个人觉得比较难的一道题:机器人路程问题,一个机器人,只能往下或者往右走,当前格子的数值表示下一次可以走得多远。
在这里插入图片描述
求机器人到左下角的所有路数。

for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                t=a[i][j];
                for(int k=0;k<=t&&i+k<=n;k++)
                {
                    for(int q=0;q<=t-k&&j+q<=m;q++)
                    {
                        if(q==0&&k==0)
                            continue;
                    dp[i+k][j+q]=((dp[i+k][j+q])+(dp[i][j]))%10000;
                    }
                }
            }
        }

因为是一个表格,所以开了二维数组,这样要是想要遍历所有情况就一定至少是双重循环,然后写出双重循环遍历所有点,在每个循环里在进行判断,当前向右走的步数和向下走的步数,这样就是四重循环了,幸好表格行列数较小,不会出现超时。这个动态转移方程成的核心在于找到当前点,然后找出每到他的可能路径,这道题一开始想的时候是按照能量为核心,找到一个下一步的可能范围,然后将新范围开始判断不断判断,这样单次的循环次数会减少,但是这样实现不知道进行几重循环,一开始想用while,但是编译总有问题,改了很久,代码很长,后来觉得自己思路有问题,就到CSDN上看了好几个别人ac的代码,发现别人在列出的动态转移方程已经包含所有情况,不需要那么多循环,因为每个点都可以被看做成一个子问题,即到这个点的路径有多少,dp[i+k][j+q]=((dp[i+k][j+q])+(dp[i][j]))

本周学习感悟和收获

其实这样找动态转移方程也是dp的一个基本思路,像开头说的,要找动态转移方程,那么就要得到一个关系,这个关系就是子问题关系,把大问题转换为一个小问题,找大问题与小问题之间的关系,然后再次把小问题分割…这样循环,直到遍历所有问题,这就是我目前对于dp问题解题思路的一个整理,因为题目做的都比较吃力,所以把已经ac的问题都写了一个大体的思路,然后反复看了好几遍,发现有时候,dp部分还是转不过来,总感觉缺少情况,到了自己写的时候真的缺少了一些情况,这周看了许多优秀的ac代码,有各种各样的,其中机器人那道题还有深度搜索等方法,类似与递归,代码长度也是我四重循环的一半多,感觉自己目前写出的代码还是太简单,与别人的存在很大的差距,这次的训练题还要继续琢磨,争取全部吃透。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值