题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1712
题目大意:
ACboy要开始选课了,上一门课能够获得的收益和他上这门课的时间是有关的,然后给你若干门课,让你帮他进行选课,
每一门课自然是只能选择一个课程时长,问你如何选择,才能使ACboy获得的受益最大。
思路:
分组背包,每门课只能选择一种学习时长
这里的组就是每门课程,价值v是总的学习时长,每门课程的所有的i就是该门课程所学习的时间
设dp[i][j]表示前i门课程花费时间j取得的最大收益
那么dp[i][j] = max(dp[i -1][j],dp[i - 1][j - t] +a[i][t])t表示第i门课程花费j天的时间
下面用的是二维数组,也可以用滚动数组,不过枚举j的时候需要逆序,道理和01背包是一样的
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 const int INF = 0x3f3f3f3f; 6 const int maxn = 1e2 + 10; 7 int T, n, m, cases; 8 int dp[maxn][maxn]; 9 //dp[i][j]表示前i门课花费j天取得的最大收益 10 //dp[i][j] = max(dp[i-1][j], dp[i-1][j-t] + a[i][t])t为第i门课花费的时间 11 int a[maxn][maxn]; 12 int main() 13 { 14 while(cin >> n >> m && (n + m)) 15 { 16 memset(dp, 0, sizeof(dp)); 17 memset(a, 0, sizeof(a)); 18 for(int i = 1; i <= n; i++) 19 for(int j = 1; j <= m; j++) 20 cin >> a[i][j]; 21 for(int i = 1; i <= n; i++)//枚举课程 22 { 23 for(int j = 0; j <= m; j++)//枚举已经花费的天数 24 { 25 for(int t = 0; t <= j; t++)//枚举第i门课需要花费的天数 26 { 27 if(j >= t)dp[i][j] = max(dp[i][j], dp[i - 1][j - t] + a[i][t]); 28 } 29 } 30 } 31 int ans = 0; 32 for(int i = 0; i <= m; i++)ans = max(ans, dp[n][i]); 33 cout<<ans<<endl; 34 } 35 return 0; 36 }