POJ1285-Combinations, Once Again

Given n objects you’d have to tell how many different groups can be chosen if r objects are taken at a time.
Input
Input consists of less than 100 test cases. Each test case begins with two integers n (0 < n <= 50), m (0 <= m <= n). The next line will contain the labels (numbers in the range 1 to n) of the n objects you are to choose from. Two objects with the same label are considered equivalent. Then in the last line for that test case, you’d have m values for r. There will be a single space separating two consecutive numbers in a line. Input is terminated by a test case where n=0, you must not process this test case.
Output
For each test case, print the test case number. And for each query number r, print the number of different groups that can be formed if r objects are taken from the given n objects. You can assume that for all input cases, the output will always fit in a 64-bit unsigned integer and (0<=r<=n).
Sample Input
5 2
1 2 3 4 5
2 1

4 1
1 2 3 4
2

0 0
Sample Output
Case 1:
10
5
Case 2:
6

分析:

题意:
第一行给出两个整数n和m,然后第二行给出n个不大于n的整数,然后第三行是m个询问,每个询问输入一个不大于n的整数k,表示从输入的n个数中取k个数的不同取法有多少种?

解析:
怎么说呢?像多重背包!
们用dp[i][j]表示在前i种物品中取j个的办法!所以状态转移方程为:
dp[i][j]=dp[i][j]+dp[i-1][j-k];k表示第i种物品取k件。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 55

using namespace std;

long long dp[N][N];
int num[N];

int main()
{
	int n,m,k,t=0,x;
	while(~scanf("%d%d",&n,&m)&&n+m)
	{
		t++;
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&x);
			num[x]++;
		}
		dp[0][0]=1;
		for(int i=1;i<=n;i++)
		{
			for(int j=0;j<=n;j++)
			{
				for(int k=0;k<=num[i]&&k<=j;k++)
				{
					dp[i][j]+=dp[i-1][j-k];
				}
			}
		}
		printf("Case %d:\n",t);
		for(int i=1;i<=m;i++)
		{
			scanf("%d",&k);
			printf("%lld\n",dp[n][k]);
		}
		memset(num,0,sizeof(num));
		memset(dp,0,sizeof(dp));
	}
	return 0;
}
发布了46 篇原创文章 · 获赞 16 · 访问量 378

猜你喜欢

转载自blog.csdn.net/weixin_43357583/article/details/105252067