HDU 5410 CRB and His Birthday (2015年多校比赛第10场)
2015-08-21 11:12
267 查看
1.题目描述:点击打开链接
2.解题思路:本题是完全背包问题的一种变形。根据题意描述,每种物品的价值随着A[i]是线性变化的,但是并不随着B[i]线性变化,B[i]仅仅是在第一次挑选第i件物品是才算入,其他时候均不算入。因此,这里的状态要比普通的完全背包增加一个维度:是否是第一次选第i件物品,即用(i,j,flag)表示当前背包容量为j时,是否为第一次选第i件物品时的最大价值。那么不难得到如下状态转移方程:
dp(i+1,j,0)=max{dp(i,j,0),dp(i,j,1)};
dp(i+1,j,1)=max{dp(i+1,j-w[i],0)+A[i]+B[i],dp(i+1,j-w[i],1)+A[i]}; (j≥w[i])
第一个方程表示不选第i件物品时,它的最大值来源于买前i件物品时候的最大值。第二个方程表示选第i件物品时,如果第i件物品时第一次被选择,那么等于dp(i+1,j-w[i],0)+A[i]+B[i],如果他已经被选过了,那么等于dp(i+1,j-w[i],1)+A[i]。取两个的较大者即可。
3.代码:
同样的,这个方程可以去掉i的维度,变成一个二维数组。
2.解题思路:本题是完全背包问题的一种变形。根据题意描述,每种物品的价值随着A[i]是线性变化的,但是并不随着B[i]线性变化,B[i]仅仅是在第一次挑选第i件物品是才算入,其他时候均不算入。因此,这里的状态要比普通的完全背包增加一个维度:是否是第一次选第i件物品,即用(i,j,flag)表示当前背包容量为j时,是否为第一次选第i件物品时的最大价值。那么不难得到如下状态转移方程:
dp(i+1,j,0)=max{dp(i,j,0),dp(i,j,1)};
dp(i+1,j,1)=max{dp(i+1,j-w[i],0)+A[i]+B[i],dp(i+1,j-w[i],1)+A[i]}; (j≥w[i])
第一个方程表示不选第i件物品时,它的最大值来源于买前i件物品时候的最大值。第二个方程表示选第i件物品时,如果第i件物品时第一次被选择,那么等于dp(i+1,j-w[i],0)+A[i]+B[i],如果他已经被选过了,那么等于dp(i+1,j-w[i],1)+A[i]。取两个的较大者即可。
3.代码:
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<algorithm> #include<cassert> #include<string> #include<sstream> #include<set> #include<bitset> #include<vector> #include<stack> #include<map> #include<queue> #include<deque> #include<cstdlib> #include<cstdio> #include<cstring> #include<cmath> #include<ctime> #include<cctype> #include<functional> using namespace std; #define me(s) memset(s,0,sizeof(s)) #define rep(i,n) for(int i=0;i<(n);i++) typedef long long ll; typedef unsigned int uint; typedef unsigned long long ull; typedef pair <int, int> P; const int N=2000+10; int dp [2]; int A ,B ; int w ; int main() { int T; for(scanf("%d",&T);T--;) { int M,n; scanf("%d%d",&M,&n); for(int i=0;i<n;i++) scanf("%d%d%d",&w[i],&A[i],&B[i]); me(dp); for(int i=0;i<n;i++) for(int j=0;j<=M;j++) { dp[i+1][j][0]=max(dp[i][j][0],dp[i][j][1]); if(j>=w[i]) dp[i+1][j][1]=max(dp[i+1][j-w[i]][0]+A[i]+B[i],dp[i+1][j-w[i]][1]+A[i]); } int ans=max(dp [M][0],dp [M][1]); printf("%d\n",ans); } }
同样的,这个方程可以去掉i的维度,变成一个二维数组。
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<algorithm> #include<cassert> #include<string> #include<sstream> #include<set> #include<bitset> #include<vector> #include<stack> #include<map> #include<queue> #include<deque> #include<cstdlib> #include<cstdio> #include<cstring> #include<cmath> #include<ctime> #include<cctype> #include<functional> using namespace std; #define me(s) memset(s,0,sizeof(s)) #define rep(i,n) for(int i=0;i<(n);i++) typedef long long ll; typedef unsigned int uint; typedef unsigned long long ull; typedef pair <int, int> P; const int N=2000+10; int dp [2]; int A ,B ; int w ; int main() { int T; for(scanf("%d",&T);T--;) { int M,n; scanf("%d%d",&M,&n); for(int i=0;i<n;i++) scanf("%d%d%d",&w[i],&A[i],&B[i]); me(dp); for(int i=0;i<n;i++) for(int j=0;j<=M;j++) { dp[j][0]=max(dp[j][0],dp[j][1]); if(j>=w[i]) dp[j][1]=max(dp[j-w[i]][0]+A[i]+B[i],dp[j-w[i]][1]+A[i]); } int ans=max(dp[M][0],dp[M][1]); printf("%d\n",ans); } }
相关文章推荐
- 机器学习--python之学会如何从文件逐行读取数据
- 如何printf64位整型!
- 代码实现UIPickerView
- (leetcode) Remove Duplicates from Sorted Array II
- hadoop随手笔记
- Java进阶01 String类
- Linq中的TakeWhile和SkipWhile的用法
- c# List<T>与ObservableCollection<T>
- Openstack kilo指南安装与实践(1)
- 测试Heartbeat
- Android中处理崩溃异常
- linux遍历目录C语言
- UVAlive 3662 Another Minimum Spanning Tree 莫队算法,曼哈顿最小生成树
- PostgreSQL学习手册-模式Schema(转)
- Quartz.net 的简单使用,创建定时任务
- 正则表达式1
- Angularjs中作用域与模板之间的关系
- 为什么8位有符号数的范围为“-128 — +127”?(转载加补充)
- SQL-Oracle异常--java.sql.SQLDataException: ORA-01861: 文字与格式字符串不匹配
- 字符串按位置复制,并统计新字符串长度