POJ 3046 Ant Counting ( 多重集组合数 经典DP )
题意 : 有 n 种蚂蚁,第 i 种蚂蚁有ai个,一共有 A 个蚂蚁。不同类别的蚂蚁可以相互区分,但同种类别的蚂蚁不能相互区别。从这些蚂蚁中分别取出S,S+1...B个,一共有多少种取法。
分析 :
实际就是要解决 => 从 n 种物品中取出 m 个有多少种取法 ( 同种无法区分 )
计数问题的 DP 定义必须保证不重复计数
这里定义 dp[i+1][j] => 从前 i 种物品中取出 j 个的组合数
根据定义为了从前 i 种物品中取出 j 个,可以从前 i-1 中取出 j-k 个并从 i 种中取出 k 个
即 dp[i+1][j] = ∑dp[i][j-k] 【 0 ≤ k ≤ min(j, ant[i]) 】
但是这个递推式的求和太耗时间,实际可以优化,考虑两种情况 j ≤ ant[i] 和 j > ant[i]
① j ≤ ant[i] ( 即 j-1 < ant[i] )
此时 ∑ 的上界 min( j, ant[i] ) = j ,将式子展开有 dp[i][0]+dp[i][1]+dp[i][2]...dp[i][j] ( k 从大到小枚举 )
将展开式的 dp[i][j] 取出来那么将得到 ∑dp[i][j-1-k] 【 0 ≤ k ≤ j-1 】( 其实这个就是 dp[i+1][j-1] !!! )
那么最后 dp[i+1][j] = dp[i+1][j-1] + dp[i][j]
② j > ant[i]
此时 ∑ 的上界 min( j, ant[i] ) = ant[i],将式子展开有 dp[i][j-ant[i]]+dp[i][j-ant[i]+1]...dp[i][j]
对比 ① 的结果,很明显如果用 ① 的结果 - dp[i][j-ant[i]-1] 就能得到上面的展开式了!
所以 ② 的情况下,dp[i+1][j] = ( dp[i+1][j-1] + dp[i][j] ) - dp[i][j-ant[i]-1]
#include<stdio.h> #include<string.h> using namespace std; const int mod = 1000000; int dp[1010][100010]; int num[1010]; int main(void) {int T, A, S, B;while(~scanf("%d %d %d %d", &T, &A, &S, &B)){memset(num, 0, sizeof(num));for(int temp,i=1; i<=A; i++)scanf("%d", &temp),num[temp-1]++;for(int i=0; i<=T; i++)dp[i][0] = 1;for(int i=0; i<T; i++){for(int j=1; j<=B; j++){if(j - 1 - num[i] >= 0)dp[i+1][j] = (dp[i+1][j-1] + dp[i][j] - dp[i][j-1-num[i]] + mod)%mod;elsedp[i+1][j] = (dp[i+1][j-1] + dp[i][j])%mod;}}int ans = 0;for(int i=S; i<=B; i++)ans = (ans + dp[T][i])%mod;printf("%d\n", ans);}return 0; }
View Code
其实 DP 的阶段 ( 数组第一维 ) 只跟前一个有关系,故用滚动数组优化
#include<stdio.h> #include<string.h> using namespace std; const int mod = 1000000; int dp[2][100010]; int num[1010]; int main(void) {int T, A, S, B;while(~scanf("%d %d %d %d", &T, &A, &S, &B)){memset(num, 0, sizeof(num));for(int temp,i=1; i<=A; i++)scanf("%d", &temp),num[temp-1]++;int idx = 0;dp[idx][0] = dp[idx^1][0] = 1;for(int i=0; i<T; i++,idx^=1){for(int j=1; j<=B; j++){if(j - 1 - num[i] >= 0)dp[idx^1][j] = (dp[idx^1][j-1] + dp[idx][j] - dp[idx][j-1-num[i]] + mod)%mod;elsedp[idx^1][j] = (dp[idx^1][j-1] + dp[idx][j])%mod;}}int ans = 0;for(int i=S; i<=B; i++)ans = (ans + dp[idx][i])%mod;printf("%d\n", ans);}return 0; }
View Code
转载于:https://www.cnblogs.com/LiHior/p/8143884.html
POJ 3046 Ant Counting ( 多重集组合数 经典DP )相关推荐
- Ant Counting多重集组合数
Ant Counting 题目描述: 有一天,贝茜无聊地坐在蚂蚁洞前看蚂蚁们进进出出地搬运食物.很快贝茜发现有些蚂蚁长得几乎一模一样,于是她认为那些蚂蚁是兄弟,也就是说它们是同一个家族里的成员.她也发 ...
- POJ 3046 Ant Counting
题目链接 题意 一共有T种蚂蚁编号从1 到 T,给出A个蚂蚁序列,问任取n个蚂蚁一共可以组几种集合,求S到B的种类和 AC dp 状态转移方程为: K表示当前蚂蚁的数目 #include <io ...
- POJ 3046 Ant Counting(递推,和号优化)
计数类的问题,要求不重复,把每种物品单独考虑. 将和号递推可以把转移优化O(1). f[i = 第i种物品][j = 总数量为j] = 方案数 f[i][j] = sigma{f[i-1][j-k], ...
- bzoj 1630 2023: [Usaco2005 Nov]Ant Counting 数蚂蚁(有重复元素的组合数)
2023: [Usaco2005 Nov]Ant Counting 数蚂蚁 Time Limit: 4 Sec Memory Limit: 64 MB Submit: 281 Solved: 18 ...
- 多重集表示合json数据_计数DP(划分数,多重集组合数)
划分数:把n个无区别的物品划分成不超过m组. dp[i][j]=j的i划分的总数. dp[i[j]=dp[i][j-i]+dp[i-1][j] 即:将j个物品分成i份,有两种情况:每份划分都大于等于1 ...
- 经典dp最长递增子序列
经典dp最大递增子序列, 看了好长时间,看了好多版本.最终因为这个看懂,也觉得这个是最全面的吧,我感觉我好菜啊. http://wenku.baidu.com/view/bed07b15552707 ...
- 【组合数学】排列组合 ( 多重集组合数示例 | 三个计数模型 | 选取问题 | 多重集组合问题 | 不定方程非负整数解问题 )
文章目录 一.多重集组合示例 二.三个计数模型 排列组合参考博客 : [组合数学]基本计数原则 ( 加法原则 | 乘法原则 ) [组合数学]集合的排列组合问题示例 ( 排列 | 组合 | 圆排列 | ...
- poj 3728 The merchant// lca(倍增实现) + dp || tarjan+并查集路径上dp
poj 3728 The merchant// lca(倍增实现) + dp Time Limit: 3000MS Memory Limit: 65536K Total Submissions: ...
- poj 2386 Lake Counting
poj 2386 Lake Counting 题目链接:http://poj.org/problem?id=2386 题目大意:数湖. 题目 ...
最新文章
- 【转】android的startActivityForResult学习心得
- OpenShift 之 Image Registry、Image 和 ImageStream 概念和相关操作
- 黑马lavarel教程---10、lavarel模型关联
- Django(part17)--form表单提交数据
- c语言中指,浅析C语言中指与数组.doc
- SharePoint 2010 master page 控件介绍(5):其他
- C语言 fwirte 函数 - C语言零基础入门教程
- 什么叫显示动力学_通过流体动力学研究找到制作煎饼的最佳方法
- 2.nginx 配置
- 自动驾驶_感知_分割_车道线检测
- SuperMap iClient3D for WebGL 示范案例(一)倾斜模型加载
- SharePoint2010探索日志
- python连接阿里云服务器_阿里云服务器python
- 浅谈Linux管线命令grep
- 论文图片绘制 Python绘制多分类混淆矩阵及可视化(颜色随正确率渐变)
- WPF图片背景色过滤
- 中文转换为日文的几点注意事项
- 腾讯云 直播 OBS 在线推流
- 管你 JDK 还是 Linux,我 Netty 稳坐钓鱼台
- TortoiseGit GitLab使用教程
热门文章
- c语言快速排序_Damp;C思想-快速排序算法
- 计算机小白学生物信息的难度,基因表达数据分析,对于还是分子生物学小白的我来说太难了。。。...
- java设计app_一个APP的诞生——从零开始设计你的手机应用
- java全局变量和局部变量_Java 10:局部变量类型推断
- aws rds恢复数据库_Amazon RDS – AWS关系数据库服务
- Python字符串endswith()
- 了解SQL INSERT INTO SELECT语句
- 如何在Windows 10上安装Python
- Akka定义Actors和消息《two》译
- spire.pdf系列文章