HDU_1712 ACboy needs your help(DP)
来源:互联网 发布:知乎怎么匿名提问 编辑:程序博客网 时间:2024/05/20 14:42
ACboy needs your help
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4538 Accepted Submission(s): 2428
Problem Description
ACboy has N courses this term, and he plans to spend at most M days on study.Of course,the profit he will gain from different course depending on the days he spend on it.How to arrange the M days for the N courses to maximize the profit?
Input
The input consists of multiple data sets. A data set starts with a line containing two positive integers N and M, N is the number of courses, M is the days ACboy has.
Next follow a matrix A[i][j], (1<=i<=N<=100,1<=j<=M<=100).A[i][j] indicates if ACboy spend j days on ith course he will get profit of value A[i][j].
N = 0 and M = 0 ends the input.
Output
For each data set, your program should output a line which contains the number of the max profit ACboy will gain.
Sample Input
2 2
1 2
1 3
2 2
2 1
2 1
2 3
3 2 1
3 2 1
0 0
Sample Output
3
4
6
题解
这是一道典型的分组背包问题,但是在把这个问题归类之前,先试着自己找思路解决这个问题。
一共有M天要分给N门课程,给我们了矩阵数组,让我们求出最大的复习效率。我们应该明白:复习时间的不同意味着得分的不同,但是对于每门课复习时间一定是确定的,前面课程复习时间的选择会对后面产生影响。我们很容易想到可以设置dp[i][j]表示前i门课一共复习j天的最大效率。所以:dp[i][j]=max(dp[i][j],dp[i-1][x]+A[i][j - x ])(0<=x<=j);
上面的思路其实是很清晰的,写出代码也很简单。下面我们看分组背包的定义,再对分组背包有更加深刻的理解。
分组背包:
有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。这些物品被划分为若干组,每组中的物品互相冲突,最多选一件。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
对照分组背包的定义,我们发现分组背包其实很好理解,分组之间互相影响,一个分组内只能选取一件,又归结为01背包问题,那么问题也就很好解决了。一维数组其实就可以。
使用一维数组的伪代码如下:
1 for 所有的组k
2 do for v V to 0
3 do for 所有的i属于组k
4 do f [v] = max{f[v],f[v-c[i]] + w[i]}
但是有两点需要注意:
1.“for v=V..0“这一层循环必须在“for 所有的i属于组k”之外。这样才能保证每一组内的物品最多只有一个会被添加到背包中。
2.类似01背包,第二层for循环一定是倒序。其实对倒序的理解一直有问题,我之前认为倒序的目的是01背包防止多次加入,但是从表达式我又认为是会改变滚动数组的值,其实两者的意思是一样的,一个是原理,一个是结果。所以这道题将分组内视为01背包就更好理解了。
二维dp代码:
#include <iostream>#include <stdio.h>#include <stdlib.h>#include <cstring>#include <limits.h>#define MAX_N 120using namespace std;//复习第i门课,已复习了j天的最大收益int dp[MAX_N][MAX_N];int N,M,result;int A[MAX_N][MAX_N];int main(){ while( scanf("%d%d",&N,&M) && N+M ) { for( int i = 1; i <= N; i++ ) for( int j = 1; j <= M; j++ ) scanf("%d",&A[i][j]); memset(dp,0,sizeof(dp)); result = 0; for( int j = 0; j <= M; j++ ) { dp[1][j]=A[1][j]; result=max(result,dp[1][j]); } for( int i = 2; i <= N; i++ ) { for( int j = 0; j <= M; j++ ) { for( int t = 0; t <= j; t++ ) dp[i][j]=max(dp[i][j],dp[i-1][t]+A[i][j-t]); result=max(result,dp[i][j]); } } printf("%d\n",result); } return 0;}
一维DP代码:
#include <iostream>#include <stdio.h>#include <stdlib.h>#include <cstring>#include <limits.h>#define MAX_N 120using namespace std;//花费时间i所得到的最大收益int dp[MAX_N];int N,M,result;int A[MAX_N][MAX_N];int main(){ while( scanf("%d%d",&N,&M) && N+M ) { for( int i = 1; i <= N; i++ ) for( int j = 1; j <= M; j++ ) scanf("%d",&A[i][j]); memset(dp,0,sizeof(dp)); for( int i = 1; i <= N; i++ ) { for( int j = M; j >= 0; j-- ) { for( int t = 0; t <= j; t++ ) dp[j]=max(dp[j],dp[j-t]+A[i][t]); } } printf("%d\n",dp[M]); } return 0;}
- HDU_1712 ACboy needs your help(DP)
- ACboy needs your help (HDU_1712) 分组背包
- ACboy needs your help(DP)
- HDU 1712 ACboy needs your help(DP 分组背包)
- HDU 1712 ACboy needs your help(DP)
- hdu1712---ACboy needs your help(dp,分组背包)
- HDU 1712 ACboy needs your help(泛化物品dp)
- hdu 1712 ACboy needs your help (DP)
- HDU 1712 ACboy needs your help DP
- ACboy needs your help
- ACboy needs your help
- ACboy needs your help
- hdu1702(ACboy needs your help again!)
- ACboy needs your help(分组背包)
- ACboy needs your help(分组背包)
- ACboy needs your help again!(1702)
- ACboy needs your help(HDU-1712)
- hdu acboy needs your help
- 数位DP hdu 2089
- 团队管理的简单总结:少即是多,体力透支,负能量管理,自我进化团队,沟通
- Java中四种访问权限总结
- mysql常见解决问题
- 8种垂直居中的方法
- HDU_1712 ACboy needs your help(DP)
- hdu 2602 01背包深入优化
- Unity3D之GUI基础以及常用GUI控件使用
- 2015/02/08
- Beijing Guards
- mysql常用命令大全(百度文库下载的,备忘一下)
- Mac快捷键
- Android中UI线程与后台线程交互设计
- Java Mac Eclipse Console 显示全部的输出