ZOJ3164【背包问题(好题)】
来源:互联网 发布:java用两个栈实现队列 编辑:程序博客网 时间:2024/05/20 00:38
%%%%%%%%%%%%%%%岐爷
这一发从来没写过这么旺盛的背包问题。。。
想法很多,但是好难执行。
题意:
有N种饼干,1-N
每种最多想买Ki个,ki等于0的话没有上界
对于第i种饼干的权值是Ei
第i种饼干的价格Pi
有D钱。
还有G组
每组只能选一种。
思路:
有两种背包,一种是在一定的组里,还有没有特定关系;
没有特定关系的,如果没有限定数或者限定数*花费大于总费用,直接完全背包;否则就是二进制优化的0/1背包;
有特定关系的就是一个分组背包,先预处理第i组j花费下的最优情况,且初始化每组每个花费下的价值都是-INF,然后最后dp,之前还要预处理一种物品在j花费下所能达到的最优值;
最后dp将每一个分组的价格当做一次01背包 ,最里面再for一层。
#include<bits/stdc++.h>using namespace std;const int N=1e3+50;const int INF=0x3f3f3f3f;int n,W;void zero_one(int dp[],int w,int val){ for(int i=W;i>=w;i--) if(dp[i-w]>-INF) dp[i]=max(dp[i],dp[i-w]+val);}void compelet(int dp[],int w,int val){ for(int i=w;i<=W;i++) if(dp[i-w]>-INF) dp[i]=max(dp[i],dp[i-w]+val);}void init(int dp[]){ fill(dp,dp+W+1,-INF); dp[0]=0;}int Kkk[N],Eee[N],Ppp[N];int mp[N];int dp[N],temp[N];char s[N];int w[10][N];int main(){ while(~scanf("%d%d",&n,&W)) { for(int i=1; i<=n; i++) scanf("%d%d%d",&Kkk[i],&Eee[i],&Ppp[i]); int G,len; scanf("%d",&G); getchar(); memset(mp,0,sizeof(mp)); for(int i=1; i<=G; i++) { gets(s); len=strlen(s); for(int j=0; j<len;) { if(s[j]>='1'&&s[j]<='9') { int sum=0; while(s[j]>='0' && s[j] <= '9') { sum=sum*10+s[j]-'0'; j++; } mp[sum]=i; } else j++; } } int k,ww,ept; init(dp); for(int i=1;i<=G;i++) init(w[i]); for(int i=1; i<=n; i++) { if(mp[i]) init(temp); if(!Kkk[i]||Kkk[i]*Ppp[i]>=W) { compelet(mp[i]?temp:dp,Ppp[i],Eee[i]); } else { k=1; while(k<=Kkk[i]) { ww=k*Ppp[i]; ept=k*Eee[i]; zero_one(mp[i]?temp:dp,ww,ept); Kkk[i]-=k; k<<=1; } ww=Kkk[i]*Ppp[i]; ept=Kkk[i]*Eee[i]; zero_one(mp[i]?temp:dp,ww,ept); } if(mp[i]) for(int j=0;j<=W;j++) w[mp[i]][j]=max(w[mp[i]][j],temp[j]); //预处理ww代表某一组里占花费j的最大收获 } for(int i=1;i<=G;i++) for(int j=W;j>=0;j--) for(int k=0;k<=j;k++) if(dp[j-k]>-INF&&w[i][k]>-INF) dp[j]=max(dp[j],dp[j-k]+w[i][k]); if(dp[W]>=0) printf("%d\n",dp[W]); else puts("i'm sorry..."); puts(""); } return 0;}/*2 10240 1 30 0 1010 10231 1 11 1 21 1 41 1 81 1 161 1 321 1 641 1 1283 -1 2561 1 51219 1010 10231 1 11 1 21 1 41 1 81 1 161 1 321 1 641 1 1281 1 2561 1 51219 10*/
0 0
- ZOJ3164【背包问题(好题)】
- zoj3164
- 01背包问题 (好难理解)
- nyoj 完全背包 311 (完全背包) 好题
- HDOJ Robberies(好题背包)
- hdoj Consumer 3449 (背包)好题
- [HDU 5534] Partial Tree (完全背包问题) (好题)
- vijosp1037-类背包问题&好题-搭建双塔
- 【DP】zoj3164
- poj 背包问题 提好汇总
- 背包问题(分组背包)
- hdu 4341(分组背包(好题))
- POJ 1745 Divisibility(0,1背包)(好题)
- Euro Efficiency 1252 (正负完全背包 好题)
- Robberies(逆向思维转换+01背包好题)
- 最大报销额 1864 (01背包 好题)
- hdoj In Action 3339 (dijiks++01背包) 好题
- nyoj 三国志 203 (dijst++01背包) 好题
- Codeforces - 133B - Unary (水题)
- CommVault v11新特性和战略解读
- python查找列表中的最大值
- Android多媒体开发(一)----MediaPlayer框架开始
- SPark SQL 从 DB 读取数据方法和方式 scala
- ZOJ3164【背包问题(好题)】
- A+B for Matrices
- 用Android Studio读Android源码
- DES加密算法
- 基于Spark的FPGrowth算法的运用
- Http协议(图解http读书笔记)
- 数组和指针的比较和关系以及区别
- 人工智能“六步走”学习路线
- 12.3 Dao层的设计