选课时间(题目已修改,注意读题)
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1857 Accepted Submission(s): 1493
Problem Description
又到了选课的时间了,xhd看着选课表发呆,为了想让下一学期好过点,他想知道学n个学分共有多少组合。你来帮帮他吧。(xhd认为一样学分的课没区别)
Input
输入数据的第一行是一个数据T,表示有T组数据。
每组数据的第一行是两个整数n(1 <= n <= 40),k(1 <= k <= 8)。
接着有k行,每行有两个整数a(1 <= a <= 8),b(1 <= b <= 10),表示学分为a的课有b门。
每组数据的第一行是两个整数n(1 <= n <= 40),k(1 <= k <= 8)。
接着有k行,每行有两个整数a(1 <= a <= 8),b(1 <= b <= 10),表示学分为a的课有b门。
Output
对于每组输入数据,输出一个整数,表示学n个学分的组合数。
Sample Input
2 2 2 1 2 2 1 40 8 1 1 2 2 3 2 4 2 5 8 6 9 7 6 8 8
Sample Output
2 445
1 /* 2 代码一 ---- WA 3 原因:题目中明确规定了 “一样学分的课没区别” 悲剧了,写的时候没考虑 4 5 #include <iostream> 6 #include <cstdio> 7 8 using namespace std; 9 10 int score[100]; 11 int res; 12 void DFS(int cur, int sum, int num, int n) 13 { 14 if(sum > n || cur >= num) 15 return; 16 if(sum == n) 17 { 18 ++res; 19 return; 20 } 21 DFS(cur + 1, sum + score[cur], num, n); 22 DFS(cur + 1, sum, num, n); 23 } 24 25 int main() 26 { 27 int T, n, k, a, b; 28 scanf("%d", &T); 29 while(T--) 30 { 31 res = 0; 32 // memset(score, 0, sizeof(score)); 33 scanf("%d%d", &n, &k); 34 int num = 0; 35 while(k--) 36 { 37 scanf("%d%d", &a, &b); 38 while(a--) 39 score[num++] = b; 40 } 41 DFS(0, 0, num, n); 42 printf("%d\n", res); 43 } 44 return 0; 45 } 46 */ 47 48 49 // 代码二: --- AC 50 #include <iostream> 51 #include <cstdio> 52 53 using namespace std; 54 55 int score[10]; 56 int res; 57 58 //从 学分为 1 的课程到学分为 max 的课程依次 DFS,直到修够 n 学分,或者超出限制为止 59 void DFS(int cur, int sum, int max, int n) //cur 表示当前所选学分为 cur 的课程 60 { //sum 保存已经修的学分总数 61 if(sum == n) // 注意这个 if 不能写在 下边的 if 后边 ,否则当选择最后一门课正好满足条件时会直接跳出,结果数会遗漏 62 { 63 ++res; 64 return; 65 } 66 if(sum > n || cur > max) 67 return; 68 if(score[cur] == 0) // 表示不存在学分为 cur 的课程 69 { 70 DFS(cur + 1, sum, max, n); 71 return; 72 } 73 for(int i = 0; i <= score[cur]; ++i) 74 DFS(cur + 1, sum + i * cur, max, n); 75 } 76 77 int main() 78 { 79 int T, n, k, a, b; 80 scanf("%d", &T); 81 while(T--) 82 { 83 res = 0; 84 memset(score, 0, sizeof(score)); 85 scanf("%d%d", &n, &k); 86 int max = 0; 87 while(k--) 88 { 89 scanf("%d%d", &a, &b); 90 score[a] = b; //学分为 a 的课有 b 门 91 if(max < a) 92 max = a; 93 } 94 DFS(1, 0, max, n); 95 printf("%d\n", res); 96 } 97 return 0; 98 }
代码三:-------复习回顾
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 5 using namespace std; 6 7 int cnt[10]; // cnt[i] 表示学分为i的课的数量 8 int ans, score; 9 10 void DFS(int sum, int cur) 11 { 12 if(sum == score) 13 { 14 ++ans; 15 return; 16 } 17 if(sum > score || cur > 8)//学分最多是 8 分 18 return; 19 for(int i = 0; i <= cnt[cur]; ++i) 20 DFS(sum+cur*i, cur+1); 21 } 22 23 int main() 24 { 25 int T, k, a, b; 26 scanf("%d", &T); 27 while(T--) 28 { 29 scanf("%d%d", &score, &k); 30 memset(cnt, 0, sizeof(cnt)); 31 ans = 0; 32 for(int i = 0; i < k; ++i) 33 { 34 scanf("%d%d", &a, &b); 35 cnt[a] = b; 36 } 37 DFS(0, 0); 38 printf("%d\n", ans); 39 } 40 return 0; 41 }