Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 15231 Accepted Submission(s): 5160
11 26
4 13
题目要求:用不超过100个硬币(从1,5,10,25,505种硬币选择) 组合成 n 的组合数。
限制 组合 单位个数 <= 100,需在母函数模版上再添上2层循环 来进行限制和更新。
母函数:0ms
#include <cstdio> #include <cstring> #include <algorithm> #define MAX 250+10 using namespace std; int c1[MAX][101];//c1[i][j] 表示 用j个硬币能组合成i的 组合数 int c2[MAX][101];//媒介 int num[MAX];//num[i]表示 用不超过100个硬币能组合成i 的 组合数 int coin[6] = {0, 1, 5, 10, 25, 50}; void getnum() { int k, i, j, p; int use;//当前硬币已经使用的个数 memset(c1, 0, sizeof(c1)); memset(c2, 0, sizeof(c2)); memset(num, 0, sizeof(num)); for(i = 0; i <= 100; i++) c1[i][i] = 1; for(i = 2; i <= 5; i++) { for(j = 0; j < MAX; j++)//最终项数 { for(k = 0, use = 0; k+j < MAX; k += coin[i], use++)//use记录当前硬币使用个数 { for(p = 0; p+use <= 100; p++)//控制硬币个数 不能超过100 { c2[k+j][p+use] += c1[j][p]; } } } for(j = 0; j < MAX; j++)//更新 { for(p = 0; p <= 100; p++) { c1[j][p] = c2[j][p]; c2[j][p] = 0; } } } for(i = 0; i < MAX; i++) { for(j = 0; j <= 100; j++)//累加100限制下的所有 组合数 { num[i] += c1[i][j]; } } } int main() { int n; getnum();//打表 while(scanf("%d", &n) != EOF) { printf("%d\n", num[n]); } return 0; }
背包:0ms
#include <cstdio> #include <cstring> using namespace std; int dp[251][101];//dp[i][j]记录 用j个硬币 组合成i 的组合数 int num[251]; int coin[6] = {0, 1, 5, 10, 25, 50}; void getnum() { int k, i, j, p; memset(dp, 0, sizeof(dp)); memset(num, 0, sizeof(num)); dp[0][0] = 1; for(i = 1; i <= 5; i++) { for(j = 0; j <= 250; j++) { for(k = 0; k < 100; k++)//这里k不能等于 100 { if(coin[i]+j <= 250)//还能加 就加 dp[coin[i]+j][k+1] += dp[j][k];//更新 注意硬币数自增一 else//过了250 不用考虑 break; } } } for(i = 0; i <= 250; i++) { for(j = 0; j <= 100; j++) num[i] += dp[i][j]; } } int main() { int n; getnum(); while(scanf("%d", &n) != EOF) { printf("%d\n", num[n]); } return 0; }