1. 程式人生 > >HDU 2079 dp解法

HDU 2079 dp解法

題解 tdi cep sin c代碼 char [] 題目 truct

選課時間(題目已修改,註意讀題)

Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5115 Accepted Submission(s): 3944


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門。

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 題意 中文題,不說了 題解 這題我們設一個dp[ i ]數組( i 表示學分數,dp[i]就是組成i學分的組合數),枚舉每個課程,求出包括前面課程所能組成的學分,對數組進行更新 0.0......說的自己都不明白---_---!!!。 AC代碼
 1 #include <stdio.h>
 2 #include <math.h>
 3
#include <string.h> 4 #include <stdlib.h> 5 #include <iostream> 6 #include <sstream> 7 #include <algorithm> 8 #include <string> 9 #include <queue> 10 #include <vector> 11 #define maxn 100005 12 #define maxm 50000 13 using namespace std; 14 typedef long long
ll; 15 int dp[50]; 16 struct course 17 { 18 int s; 19 int n; 20 }f[10]; 21 int main(int argc, char const *argv[]) 22 { 23 int t; 24 cin>>t; 25 while(t--) 26 { 27 int n,m; 28 cin>>n>>m; 29 memset(dp,0,sizeof(dp)); 30 for(int i=1;i<=m;i++) 31 { 32 cin>>f[i].s>>f[i].n; 33 } 34 dp[0]=1; 35 for(int i=1;i<=m;i++) //枚舉課程 36 { 37 for(int j=n;j>=f[i].s;j--) //枚舉價值,要從大到小推! 38 { 39 for(int k=1;k<=f[i].n;k++) ////枚舉這個物品的個數,如果當前枚舉到的價值能放入此物品的話,就加上之前的價值 40 { 41 if(j>=k*f[i].s) 42 dp[j]+=dp[j-k*f[i].s]; //更新數組 43 else 44 break; 45 } 46 } 47 } 48 cout<<dp[n]<<endl; 49 } 50 return 0; 51 }

另一種 從小到大推,別人寫的,摘自http://www.lai18.com/content/2463208.html

 1 #include <stdio.h>
 2 #include <math.h>
 3 #include <string.h>
 4 #include <stdlib.h>
 5 #include <iostream>
 6 #include <sstream>
 7 #include <algorithm>
 8 #include <string>
 9 #include <queue>
10 #include <vector>
11 #define maxn 100005
12 #define maxm 50000
13 using namespace std;
14 typedef long long ll;
15 int main()
16 {
17   int T, n, num, a[10], b[10], c1[41], c2[41];
18   //由於1<=num<=8,所以a,b開到10;由於1<=n<=40,所以c1,c2開到41
19   scanf("%d", &T);
20   while (T--) 
21   {
22     scanf("%d%d", &n, &num);
23     for (int i = 1;i <= num;i++)
24       scanf("%d%d", &a[i], &b[i]);
25     memset(c1, 0, sizeof(c1));
26     memset(c2, 0, sizeof(c2));
27     c1[0] = 1;//由於本題對每個a[i]有個數限制,所以不能使數組c1初始化1【那樣相當於默認學分為1的課程無限個】
28     //但是可以在相乘多項式前多乘一個1,所以賦值c1[0] = 1,同時下面是從i=1開始的
29     for (int i = 1;i <= num;i++) 
30     {//i表示乘到了第幾項
31       for (int j = 0;j <= n;j++)
32       {
33         for (int k = 0;k + j <= n&&k <= b[i]*a[i];k += a[i])//a[i]是第i個多項式的單個課程學分
34           c2[k + j] += c1[j];
35       }
36       memcpy(c1, c2, sizeof(c1));//c2賦給c1
37       memset(c2, 0, sizeof(c2));//c2清零
38     }
39     printf("%d\n", c1[n]);
40   }
41   return 0;
42 }

還可以用母函數寫 可是我不會母函數 有時間去研究研究~

HDU 2079 dp解法