Ant Counting POJ - 3046 多重集组合数
来源:互联网 发布:中老年服饰淘宝模特 编辑:程序博客网 时间:2024/05/19 18:12
题目链接:Ant Counting POJ - 3046
t种物品,每种物品有a[i]个,从中取出s个,s+1…b个,取法数相加有多少种?(同种物品没有区别)
就是挑战上的多重集组合数
n种物品,每种物品a[i]个,从中取出m个,取法有多少?
定义dp[i+1][j] := 从前i种物品种取j个,有多少种取法;
要在i种物品中取出j个,可以在i-1中物品种取j个,第i种物品不取
或者从前i-1中物品中取j-k个,k<=min(a[i], j),第i种物品取k个
即:dp[i+1][j] = dp[i][j-k] (0<=k<=min(a[i], j)
但这样需要三层循环,效率O(n*m*a[i]);
挑战上通过将上式变形的出O(mn)的公式,看不懂变形过程,但如果从实际出发,这个公式很好理解 dp[i+1][j] = dp[i][j] + dp[i+1][j-1] - dp[i][j-1-a[i]];
右边有三个部分
第一个:在前i-1种物品中取j个,第i种物品一个都不取
第二三个整体:前i种物品取了j-1个,其中第i种取了0-a[i]-1个,然后再在第i种物品种取一个
第二个部分:前i种物品取了j-1个,其中第i种取了0-a[i]个(也就是包括了第i种物品全部取了的情况,所以要减去)
第三部分:前i个物品取了j-1个,其中第i种取了a[i]个(看起来是前i-1种物品取了j-1-a[i]个,但只要再取a[i]个i物品,就是了)
还有就是,但’j-1-a[i]<0`时,第i种不可能全部取完,就不需要减去全部取完的情况了
i = 0..n-1;j = 1..m;//(dp[i][0] = 1,因为无论i=多少,取0个的方案都只有一个,所以提前初始化dp[i][0] = 1;if(j-1-a[i]>=0) dp[i+1][j] = dp[i][j] + dp[i+1][j-1] - dp[i][j-1-a[i]];else dp[i+1][j] = dp[i][j] + dp[i+1][j-1];
而这题核心代码一样的,只需要将最后的dp[t][s…b]加起来就好了;
注意这个dp不能写成一位数组,因为每次更新都同时需要前面更新过的和没更新过的数据,但如果用二维数组,就需要dp[1000][100000],1e8的int可能会mle,所以用滚动数组就好啦
#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>using namespace std;const int MAXT = 1000 + 10, MOD = 1000000;int a[MAXT], t, n, s, b, dp[2][MAXT*100];int main(){ while(cin >> t >> n >> s >> b) { memset(a, 0, sizeof(a)); memset(dp, 0, sizeof(dp)); int x; for(int i=0; i<n; ++i) { scanf("%d", &x); a[x-1]++; } dp[0][0] = dp[1][0] = 1; for(int i=0; i<t; ++i) { for(int j=1; j<=b; ++j) { if(j-1-a[i] >= 0) dp[(i+1)&1][j] = (dp[i&1][j] + dp[(i+1)&1][j-1] - dp[i&1][j-1-a[i]] + MOD) % MOD; else dp[(i+1)&1][j] = (dp[i&1][j] + dp[(i+1)&1][j-1]) % MOD; } } int ans = 0; for(int i=s; i<=b; ++i) { ans = (ans + dp[t&1][i]) % MOD; } cout << ans << endl; } return 0;}
- POJ 3046 Ant Counting(dp----多重集组合数)
- POJ - 3046 Ant Counting(多重集组合数DP)
- Ant Counting POJ - 3046 多重集组合数
- POJ 3046 Ant Counting (dp 多重集组合数)
- POJ 3046---Ant Counting(多重组合数)
- Ant Counting(多重集组合数)
- POJ3046-Ant Counting-多重集组合数
- POJ 3046 Ant Counting(dp—多重集组合数问题)
- POJ 3046 Ant Counting 题解- 多重集组合数问题(附测试数据)
- Poj 3046 Ant Counting【多重背包】
- poj 3046 Ant Counting (DP多重背包变形)
- (经典)POJ-3046 多重集组合数
- poj 3046 多重集组合数【水一下】
- POJ 3046 Ant Counting
- POJ-3046-Ant Counting
- poj 3046 Ant Counting
- poj 3046 Ant Counting
- POJ 3046 Ant Counting
- 基于最大稳定区域的图像分割算法
- 利用Java反射实现JavaBean对象相同属性复制并初始化目标对象为空的属性的BeanUtils
- HTML/CSS基础
- Vue项目搭建
- linux error: expected declaration specifiers or '...' XXX
- Ant Counting POJ - 3046 多重集组合数
- Web项目程序怎么发布部署
- 求FFFF:0到FFFF:F的字节型数据和,存放到dx中(LOOP和ds:[bx]联合运用)
- 博览网 侯捷老师C++课程 第五周笔记
- 把有交互功能的UI显示出来
- 学习BLAS库 -- TRMV
- S2 深入.NET平台和C#语言 第三章 课上练习
- 一、策略模式
- 信号量Semaphore