poj1285 Combinations, Once Again(泛化背包)

Combinations, Once Again
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 1897 Accepted: 636

Description

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

Source

题意:给你n个数,求取r个的方案数
题解:搜题解时博客上有人说这是泛化背包,说实话,这个东西看了很久都没理解,
只有等以后再来弄懂了………
代码:
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
using namespace std;

typedef long long LL;
const int N = 1000;
int num[N], que[N], n, m;
LL f[N];
int main(){
    freopen("1285.txt", "r", stdin);
    int cas = 0;
    while(~scanf("%d %d", &n, &m ) && n){
        memset(num, 0, sizeof(num));
        int tp;
        for(int i  = 0; i < n ;i++){
            scanf("%d", &tp);
            tp--;
            num[tp]++;
        }
        for(int i = 0; i < m; i++){
            scanf("%d", &que[i]);
        }
        memset(f, 0, sizeof(f));
        for(int i  = 0 ;i <= num[0]; i++){
            f[i] = 1;
        }
        for(int i = 1; i < n; i++){
            for(int j = n; j >= 1; j--){
                for(int k = max(j - num[i], 0);  k < j ; k ++){
                        f[j] += f[k];
                }
            }
        }
        cas++;
        printf("Case %d:\n", cas);
        for(int i = 0; i < m; i++){
            printf("%I64d\n", f[que[i]]);
        }
    }
    return 0;
}

 

 

转载于:https://www.cnblogs.com/zhgyki/p/9601286.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值