POJ1285 Combinations, Once Again(背包 排列组合)

时间:2021-01-01 22:16:20

背包解组合数学问题,n种物品,每种num[i]个,求取r个的方法数。

背包思想,f[j]表示当前取j个数的方法数,则状态转移方程为

f[j] += f[k](max(j - num[i], 0) <= k < j)

外层循环枚举物品,内层循环从大到小枚举空间,最内层枚举方法数。

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