1285: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 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.
输出
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).

样例输入
5 2
1 2 3 4 5
2 1

4 1
1 2 3 4
2

0 0

样例输出
Case 1:
10
5
Case 2:
6

像这种定量计算不同的解决方案就可以归结为背包问题

我们可以把他转换成一个背包问题,把每次选择的object的个数当成是背包容量,满足背包容量的方案就是 the number of different groups.

object[]数组来存储输入的数字

我们用一个二维数组result[][]来表示结果,result[s][r]表示从object[s]开始计算选取r容量的方案个数,所以result[s][r]=result[s+1][r-1]+result[k][r],其中result[s+1][r-1]表示把object[s]放入背包中后的方案个数;result[k][r]表示忽略object[s],并找到和object[s]不相等的object[k]时的解决方案的个数。

你会发现result[s][r]=result[s+1][r-1]+result[k][r],背包问题在解决的时候是需要知道后面的值的,所以需要从后面开始计算,但是背包的容量是在递减的,所以开始的位置是从object的后面开始,容量从1开始

初始化时 result[i][0]=1 因为可以理解为不向背包中放入object时,也会有一种方案(就是空啦)

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<algorithm>

using namespace std;
#define maxNumber 52
int n;
int m;
int caseNumber=1;
int object[maxNumber];
unsigned long result[maxNumber][maxNumber];
int main()
{
  while(cin>>n&&cin>>m&&n&&caseNumber<100){
    for(int i=1;i<=n;i++){
      cin>>object[i];
    }
    sort(object+1,object+n+1);
    memset(result,0,sizeof(result));
    for(int i =1;i<=n;i++)
      //initial the array
      result[i][0]=1;
    //if start from n and choose just one object, result is 1
    result[n][1]=1;

    // i is the situation of start object
    for(int i = n-1;i>=1;i--){
      // j is the capicity
      for(int j = 1; j<=n;j++){
        //result[i+1][j-1] choose the object in i situation
        result[i][j]=result[i+1][j-1];
        int k;
        for(k = i+1;k<=n;k++)
          if(object[i]!=object[k])
            break;
        //result[k][j] doesn't choose object the same as that in i situation
        result[i][j]+=result[k][j];
      }
    }
    cout<<"Case "<<caseNumber<<":"<<endl;

    while(m--){
      int testCase;
      cin>>testCase;
      cout<<result[1][testCase]<<endl;
    }

    caseNumber++;
  }
  return 0;

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值