1 条题解
-
0
解题思路
本题要求计算从给定的个物体中选取个物体时不同组合的数量。
- 数据初始化与输入处理:
- 定义数组
num[51]
记录每个标签物体的数量,dp[51][51]
用于存储动态规划的中间结果。 - 读取输入的和,以及个物体的标签,同时记录物体标签的最大值
Max
和最小值Min
。 - 用
memset
函数将num
和dp
数组初始化为0 。
- 定义数组
- 动态规划初始化:
- 对于标签为
Min
的物体,其数量为cnt
。先将dp[Min][0]
初始化为1,表示不选物体时有一种方案。 - 然后将
dp[Min][1]
到dp[Min][cnt]
都初始化为1,因为对于只有一种标签的物体,选取不同数量的方案数都是1 。
- 对于标签为
- 动态规划递推:
- 从标签
Min + 1
到Max
进行遍历。对于每个标签i
,先将dp[i][0]
设为1,表示不选物体的方案数为1 。 - 随着遍历,
cnt
累加当前标签物体的数量num[i]
。对于每个数量j
(从1到cnt
),dp[i][j]
的计算分两部分:- 一部分是不选当前标签
i
的物体,即dp[i - 1][j]
。 - 另一部分是选择当前标签
i
的物体,通过枚举选择当前标签物体的数量k
(从1到num[i]
),累加dp[i - 1][j - k]
。
- 一部分是不选当前标签
- 从标签
- 结果输出:
- 读取每个测试用例中的个值。
- 对于每个,输出
dp[Max][r]
,即从所有物体中选取个物体的不同组合数量。
#include<iostream> using namespace std; #include<cstring> int n,m,r,num[51]; unsigned long long dp[51][51]; int main(){ int nc = 1; while(cin>>n>>m&&(n||m)){ cout << "Case " << nc++ << ":" << endl; int Max = -1, Min = 100; memset(num,0,sizeof(num)); memset(dp,0,sizeof(dp)); for(int i = 0; i < n; i++){ int t; cin >> t; num[t]++; Max = max(t,Max); Min = min(t,Min); } int cnt = num[Min]; dp[Min][0] = 1; for(int i = 1; i <= cnt; i++) dp[Min][i] = 1; for(int i = Min+1; i <= Max; i++){ dp[i][0] = 1; cnt+=num[i]; for(int j = 1; j <= cnt; j++){ dp[i][j] += dp[i-1][j]; for(int k = 1; k <= num[i]; k++) dp[i][j] += dp[i-1][j-k]; } } for(int i = 0; i < m; i++){ cin >> r; cout << dp[Max][r] << endl; } } }
- 数据初始化与输入处理:
- 1
信息
- ID
- 286
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 9
- 已通过
- 1
- 上传者