[dp算法]逃离农场
【逃离农场】牛牛在农场饲养了n只奶牛,依次编号为0到n-1, 牛牛的好朋友羊羊帮牛牛照看着农场.有一天羊羊看到农场中逃走了k只奶牛,但是他只会告诉牛牛逃走的k 只奶牛的编号之和能被n整除。你现在需要帮牛牛计算有多少种不同的逃走的奶牛群。因为结果可能很大,输出结果对1,000,000,007取模。
例如n = 7 k = 4: 7只
奶牛依次编号为0到6, 逃走了4只
编号和为7的有:{0, 1, 2, 4}
编号和为14的有:{0, 3, 5, 6}, {1, 2, 5, 6}, {1, 3, 4, 6},{2, 3, 4, 5}
4只牛的编号和不会大于18,所以输出5.
输入描述: 输入包括一行,两个整数n和k(1 ≤ n ≤ 1000),(1 ≤ k ≤ 50),以空格分割。
输出描述: 输出一个整数表示题设所求的种数。
解析:
使用dp[i][j][t]表示前i+1头奶牛中选取j头的和除以n余为t的方案数。
则方案分为两种:选取了第i头奶牛和没有选取第i头奶牛两个子问题
状态控制方程为:dp[i][j][t]=dp[i−1][j][t]+dp[i−1][j−1][((t+n)−i)%n]
不用空间压缩的算法:
int func(int n, int k) {vector<vector<vector<int>>> dp;vector<int> vec1(n,0); //余数的范围0~n-1共n个,全部初始化为0vector<vector<int>> vec2;vec2.resize(k+1,vec1); // 逃跑o~k只dp.resize(n,vec2); // n只牛//初始赋值 ,i = 0时, 存在1头牛,选出0个,余n为0,这是一种唯一方案; //选出1个,余n为0,也是一种唯一方案dp[0][1][0] =dp[0][0][0] = 1;//编号为i的前i+1头奶牛for (auto i = 1; i < n; i++) {//选择j头奶牛。注意j的退出条件是min(k,i+1),因为i对应有i+1头牛for (auto j = 0; j <= min(k, i+1); j++){for (auto t = 0; t < n; ++t)//余t{//因为这里会涉及到 j-1,需要确保它大于0if (j > 0){ dp[i][j][t] = (dp[i-1][j][t] + dp[i-1][j - 1][((t + n) - i) % n]);} else{//当j==0的时候,也就是一头牛都没逃走,这时余数必须是0才有值,取其他都是0if (j == 0 && t==0){ dp[i][j][t] = 1;}}}}}return dp[n-1][k][0];
}
注意初始化条件和j的退出条件
留意到状态转移方程,其实每次计算新的i的时候,它只会用到i-1的二维数组的值。所以可以只使用一个二维数组去保存状态值就行了。所以状态方程可以写成
dp[j][t] = (dp[j][t] + dp[j - 1][((t + n) - i) % n]);
int func2(int n, int k) {vector<vector<int>> dp;vector<int> vec(n,0);dp.resize(k + 1, vec);dp[1][0] = dp[0][0] = 1; //网上有些写法,只写了dp[0][0] = 1其实是不对的for (auto i = 1; i < n; i++)//前i+1头奶牛{for (auto j = min(k, i+1); j > 0; --j)//选择j头奶牛。{for (auto t = 0; t < n; ++t)//余t{dp[j][t] = (dp[j][t] + dp[j - 1][((t + n) - i) % n]) ;}}}return dp[k][0];
}
注意:j要使用递减的方式,因为状态方程依赖于j-1,如果我们使用递增,就会先计算了j-1,然后再计算j,这样,j-1就变成了当前i循环的j-1,而不是上一次i循环的j-1。比如先计算i=3,当计算i=4时,先计算j-1,计算完了j-1之后,然后你再计算j的时候,i=3的j-1已经被覆盖,你使用的就是i=4的j-1,这是不对的。所以一定要用递减的方式循环j
[dp算法]逃离农场相关推荐
- boost::geometry模块多边形DP算法简化示例
boost::geometry模块多边形DP算法简化示例 实现功能 C++实现代码 实现功能 boost::geometry模块多边形DP算法简化示例 C++实现代码 #include <boo ...
- dp笔记:关于DP算法和滚动数组优化的思考
从网上总结了一些dp的套路以及对滚动数组的一些思考,现记录如下,希望以后回顾此类算法时会有所帮助. 目录 1.DP算法经验 1.DP算法核心: 2.DP算法类别以及例题 例1:三步问题 例2:最小路径 ...
- Leetcode 64. 最小路径和 -- DP算法
Time: 20190831 题目描述 给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小. 说明:每次只能向下或者向右移动一步. 示例: 输入: ...
- AIS数据压缩-改进的DP算法(Improved DP algorithm)
在上两篇博客中,对AIS数据进行压缩用了两种方法: 1.AIS数据压缩-时间比率算法(Time-Ratio-algorithm) 2.AIS数据压缩-时间比率_速度_航向算法(Time-Speed-H ...
- 灰度图像压缩 DP算法 位运算详解
作者码字不易,白天敲代码,晚上熬夜赶报告,要转载请注明出处哦,程序猿的辛酸泪 目录 位运算回顾 压缩过程 解压过程 关于一个莫得感情的小bug 实用小工具的下载地址 完整版代码 位运算回顾 若 a = ...
- 第十四周DP算法总结
这周自己主要再看DP算法的博客,感觉DP这一部分内容确实比之前的都要麻烦一些,最后攻克这一部分难题还是挺好的. 这周自己总结了一些题型,以及一些方法思路,最后再把动态规划和之前的分治和贪心做一下比较. ...
- 模式识别读书报告---关于DP算法的…
我喜欢玩星际争霸,当我操作我的部队用快捷键A进攻敌人时,部队就会自动避开障碍物attack目标.当时我就对为什么部队能自动选择最短的路进攻产生了兴趣,它是用什么算法实现的.而且当你的对手是电脑时,是用 ...
- DP 算法: cutting a rod
给定一个问题, 能够使用动态规划的方法解决的一个标志就是, 这个问题具有最优子结构(optimal substructure). 我们可以认为, 能够使用DP算法的问题首先能够分解为子问题. 而且我们 ...
- 动态规划算法python_动态规划——DP算法(Dynamic Programing)
一.斐波那契数列(递归VS动态规划) 1.斐波那契数列--递归实现(python语言)--自顶向下 递归调用是非常耗费内存的,程序虽然简洁可是算法复杂度为O(2^n),当n很大时,程序运行很慢,甚至内 ...
最新文章
- 纪念计算机之父阿兰·图灵诞辰109周年
- 【 FPGA 】超声波测距小实验(一)
- poj1189 简单dp
- C语言试题十二之m个人的成绩存放在score数组中,请编写函数function,它的功能是:将低于平均分的人数作为函数值返回,将低于平均分的分数放在below所指定的数组中。
- Receiver type ‘X’ for instance message is a forward declaration
- 领导看了我写的关闭超时订单,让我出门左转!
- 13.卷1(套接字联网API)---守护进程和 inetd 超级服务器
- 软件工程--螺旋模型详解
- 本地文件怎么传到linux服务器,本地文件传到linux服务器
- 购买代购的产品算违法吗——看空姐代购被判刑有感
- chromecast协议_如何将Chromecast用作快速信息仪表板
- vue + element-ui 实现分页功能
- 一个男人的一生应该有几个女人?
- 跨境知道快讯:亚马逊推出“Buy with Prime”服务
- 汽车VIN码与二手车市场
- 微型计算机主板,四款ITX主板PK鉴赏
- 【线代】 线性方程组的解
- 2019 My excel
- Android系统触摸屏移植后出现小圆圈
- Bootstrap系列之卡片(Cards)