[HDU 3535] AreYouBusy 混合背包
2015-07-28 09:35
573 查看
http://acm.hdu.edu.cn/showproblem.php?pid=3535
题意:输入两个数 n, T 表示有 n 类工作和 T 个单位的时间,然后输入 n 类工作,每一类先输入两个数 m,s 表示这类工作包含 m 个工作, 如果 s == 0 表示这类工作里面至少选一个去做, s == 1 表示这类工作里面做多只能做一个, s == 2 表示这类工作你随便选几个, 然后输入 m 行的两个数表示工作需要的时间和能得到的价值。
思路:
第一类:至少选一项,对于这一组的dp的初值,应该全部赋为负无穷,这样才能保证不会出现都不选的情况。
状态转移方程为 dp[i][k] = max{ dp[i][k], dp[i-1][k-vol] +v al, dp[i][k-vol]+val }。
dp[i][k]是不选择当前工作;
dp[i-1][k-vol]+val是选择当前工作,但是是第一次在本组中选;
dp[i][k-cost[j]]+val[j]表示选择当前工作,并且不是第一次取。
第二类:最多选一项,
状态转移方程为dp[i][k]=max{ dp[i][k], dp[i-1][k-vol]+val}。
由于要保证得到全局最优解,所以在该组DP开始以前,应该将上一组的DP结果先复制到这一组的dp[i]数组里,因为这一组的数据是在上一组数据的基础上进行更新的。
第三类:任意选,
状态转移方程为dp[i][k]=max{ dp[i][k],dp[i-1][k-vol]+val,dp[i][k-vol]+val}。
同样要保证为得到全局最优解,先复制上一组解。
题意:输入两个数 n, T 表示有 n 类工作和 T 个单位的时间,然后输入 n 类工作,每一类先输入两个数 m,s 表示这类工作包含 m 个工作, 如果 s == 0 表示这类工作里面至少选一个去做, s == 1 表示这类工作里面做多只能做一个, s == 2 表示这类工作你随便选几个, 然后输入 m 行的两个数表示工作需要的时间和能得到的价值。
思路:
第一类:至少选一项,对于这一组的dp的初值,应该全部赋为负无穷,这样才能保证不会出现都不选的情况。
状态转移方程为 dp[i][k] = max{ dp[i][k], dp[i-1][k-vol] +v al, dp[i][k-vol]+val }。
dp[i][k]是不选择当前工作;
dp[i-1][k-vol]+val是选择当前工作,但是是第一次在本组中选;
dp[i][k-cost[j]]+val[j]表示选择当前工作,并且不是第一次取。
第二类:最多选一项,
状态转移方程为dp[i][k]=max{ dp[i][k], dp[i-1][k-vol]+val}。
由于要保证得到全局最优解,所以在该组DP开始以前,应该将上一组的DP结果先复制到这一组的dp[i]数组里,因为这一组的数据是在上一组数据的基础上进行更新的。
第三类:任意选,
状态转移方程为dp[i][k]=max{ dp[i][k],dp[i-1][k-vol]+val,dp[i][k-vol]+val}。
同样要保证为得到全局最优解,先复制上一组解。
[code]#include <cstdio> #include <cstring> #include <iostream> using namespace std; const int inf = (1<<31)-1; int dp[105][105]; int main() { int n, volume; while(cin>>n>>volume){ int m, s, val, vol; memset(dp, 0, sizeof(dp)); for(int i = 1; i <= n; i++){ cin>>m>>s; if(s == 0){ for(int k = 0; k <= volume; k++){ dp[i][k] = -inf; } while(m--){ cin>>vol>>val; for(int k = volume; k >= vol; k--){ dp[i][k] = max(dp[i][k], dp[i][k-vol] + val);//不是第一次选 dp[i][k] = max(dp[i][k], dp[i-1][k-vol] + val);//第一次选必须由上一层传递 } } } else if(s == 1){ for(int k = 0; k <= volume; k++){ dp[i][k] = dp[i-1][k]; } while(m--){ cin>>vol>>val; for(int k = volume; k >= vol; k--){ dp[i][k] = max(dp[i][k], dp[i-1][k-vol] + val); //必须由上一次传递,保证之选一个 } } } else{ for(int k = 0; k <= volume; k++){ dp[i][k] = dp[i-1][k]; } while(m--){ cin>>vol>>val; for(int k = volume; k >= vol; k--){ dp[i][k] = max(dp[i][k], dp[i][k-vol] + val); //01背包 dp[i][k] = max(dp[i][k], dp[i-1][k-vol] + val); } } } } cout<<max(-1, dp [volume])<<endl; } return 0; }
相关文章推荐
- 开源网站
- Java StringBuffer类
- git的一些简单用法
- poj 3648 Wedding(2-sat--拓扑排序输出可行解)
- PCL1.72配置方法
- 解决企业In-House安装APP需HTTPS支持的问题
- js 小数运算问题
- EarthWarrior3D游戏ios源码
- android多媒体框架
- 音乐推荐系统比较调研(2)之场景推荐
- 1001.害死人不偿命的(3n+1)猜想 (15)
- onSaveInstanceState(Bundle)方法
- 让tableView的每个section的headerview随tableview一起滚动
- codis的proxy层HA
- Linq实现DataTable动态去重复
- zoj 3890 Wumpus(zoj 2015年7月月赛)
- [VS调试]VS2010 VS2012调试时显示加载符号导致调试特别慢
- 利用SecureCRT进行文件的传输
- Android数据保存之文件保存
- iOS注释标记(参考javadoc)