芸芸背包
2016-04-11 16:34
302 查看
【HDU 2602】 Bone Collector
01背包模版
有个背包,背包有重量上限,有一些不同的骨头,骨头有价值和重量,选一些骨头放进背包,求最大价值。#include<cstdio> #include<cstring> #include<iostream> using namespace std; const int maxn=1010; const int maxm=1010; int f[maxm]; struct obj{ int w,v; } a[maxn]; int n,V; int T; int main(){ scanf("%d",&T); while(T--){ memset(f,0,sizeof(f)); scanf("%d%d",&n,&V); for(int i=1;i<=n;i++) scanf("%d",&a[i].v); for(int i=1;i<=n;i++) scanf("%d",&a[i].w); for(int i=1;i<=n;i++) for(int j=V;j>=a[i].w;j--) f[j]=max(f[j],f[j-a[i].w]+a[i].v); printf("%d\n",f[V]); } }
【HDU 2639】Bone Collector Ⅱ
01背包第K优解
每个f[i]维护一个序列保存其前k优解#include<cstdio> #include<cstring> #include<iostream> using namespace std; const int maxn=110; const int maxv=1010; const int maxk=35; int f[maxv][maxk]; struct obj{ int v,w; } a[maxn]; int n,W,T,k; int x[maxn],y[maxn]; int main(){ scanf("%d",&T); while(T--){ memset(f,0,sizeof(f)); memset(x,0,sizeof(x)); memset(y,0,sizeof(y)); scanf("%d%d%d",&n,&W,&k); for(int i=1;i<=n;i++) scanf("%d",&a[i].v); for(int i=1;i<=n;i++) scanf("%d",&a[i].w); for(int i=1;i<=n;i++){ for(int j=W;j>=a[i].w;j--){ for(int l=1;l<=k;l++){ x[l]=f[j-a[i].w][l]+a[i].v; y[l]=f[j][l]; } for(int p1=1,p2=1,l=1;l<=k&&(p1<=k||p2<=k);){ if(x[p1]>y[p2]) f[j][l]=x[p1++]; else f[j][l]=y[p2++]; if(f[j][l]!=f[j][l-1])l++; } } } printf("%d\n",f[W][k]); } }
【HDU 2546】饭卡
01背包变形
用5元买(抢)掉最贵的,剩下的做01背包#include<cstdio> #include<cstring> #include<iostream> using namespace std; const int maxn=1010; const int maxv=1010; int f[maxv]; int w[maxn]; int n,m; int T; int main(){ while(scanf("%d",&n)&&n){ memset(w,0,sizeof(w)); for(int i=n;i>=1;i--){ scanf("%d",&w[i]); if(w[i]>w )swap(w[i],w ); } scanf("%d",&m); if(m<5){ printf("%d\n",m); continue; } memset(f,0,sizeof(f)); for(int i=1;i<n;i++){ for(int j=m-5;j>=w[i];j--) f[j]=max(f[j],f[j-w[i]]+w[i]); } printf("%d\n",m-f[m-5]-w ); } }
【HDU 1203】I NEED A OFFER!
01背包变形
f[i]表示付出i的代价收不到一份OFFER的概率,做01背包#include<cstdio> #include<cstring> #include<iostream> #include<cmath> using namespace std; const int maxn=10010; const int maxm=10010; int w[maxm]; double v[maxm],f[maxn]; int n,m; double min(double a,double b){ return a<b?a:b; } int main(){ while(~scanf("%d%d",&n,&m),n+m){ for(int i=1;i<=m;i++){ scanf("%d%lf",&w[i],&v[i]); v[i]=1.0-v[i]; } for(int i=0;i<=n;i++)f[i]=1.0; for(int i=1;i<=m;i++) for(int j=n;j>=w[i];j--) f[j]=min(f[j],f[j-w[i]]*v[i]); printf("%.1f%%\n",(1-f )*100); } }
【HDU 2995】Robbieries
01背包变形
f[i]表示抢i元之后能逃脱的概率,做01背包即可#include<cstdio> #include<cstring> #include<iostream> using namespace std; const int maxn=110; const int maxm=10010; int w[maxn]; float f[maxm]; float v[maxn]; float p; int n,m; int T; float max(float a,float b){ return a>b?a:b; } int main(){ scanf("%d",&T); while(T--){ cin>>p>>n; p=1-p; m=0; for(int i=1;i<=n;i++){ cin>>w[i]>>v[i]; v[i]=1-v[i]; m+=w[i]; } memset(f,0,sizeof(f)); f[0]=1; for(int i=1;i<=n;i++) for(int j=m;j>=w[i];j--){ f[j]=max(f[j],f[j-w[i]]*v[i]); } for(int i=m;i>=0;i--) if(f[i]>p){ printf("%d\n",i); break; } } }
【HDU 1114】Piggy-Bank
完全背包变形
已知一些硬币的值和重量,现给出一个重量,求这些硬币可能的值的最小值f[i]表示重量为i时的价值最小值,做完全背包即可
#include<cstdio> #include<cstring> #include<iostream> using namespace std; const int maxn=510; const int maxm=10010; const int INF=0x3f3f3f3f; int T,m,n; int f[maxm]; int w[maxn],v[maxn]; int main(){ scanf("%d",&T); while(T--){ int p,q; scanf("%d%d",&p,&q); m=q-p; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d",&v[i],&w[i]); for(int i=1;i<=m;i++)f[i]=INF; f[0]=0; for(int i=1;i<=n;i++) for(int j=w[i];j<=m;j++) f[j]=min(f[j],f[j-w[i]]+v[i]); if(f[m]==INF) puts("This is impossible."); else printf("The minimum amount of money in the piggy-bank is %d.\n",f[m]); } }
【HDU 1171】Big Event in HDU
多重背包
把每个物品的数量二进制拆分,然后做01背包#include<cstdio> #include<cstring> #include<iostream> using namespace std; const int maxn=1010; const int maxm=2555555; int w[maxn],num[maxn]; int f[maxm]; int n,m,T; int main(){ while(scanf("%d",&n)){ if(n<0)return 0; m=0; memset(f,0,sizeof(f)); for(int i=1;i<=n;i++){ scanf("%d%d",&w[i],&num[i]); m+=w[i]*num[i]; } for(int i=1;i<=n;i++){ int left=num[i]; for(int k=1;k <= left;k<<=1){ left-=k; int t=w[i]*k; for(int j=m/2;j>=t;j--){ f[j]=max(f[j],f[j-t]+t); } } if(left>0){ int t=left*w[i]; for(int j=m/2;j>=t;j--) f[j]=max(f[j],f[j-t]+t); } } int ans1=max(f[m/2],m-f[m/2]); int ans2=min(f[m/2],m-f[m/2]); printf("%d %d\n",ans1,ans2); } }
【HDU 2191】
多重背包模版
#include<cstdio> #include<cstring> #include<iostream> using namespace std; const int maxn=110; const int maxm=110; int w[maxm],v[maxm],num[maxm]; int f[maxn]; int n,m,T; int main(){ scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d%d%d",&w[i],&v[i],&num[i]); } memset(f,0,sizeof(f)); for(int i=1;i<=n;i++){ int left=num[i]; for(int k=1;k<=left;k<<=1){ int ww=w[i]*k; int vv=v[i]*k; left-=k; for(int j=n;j>=ww;j--) f[j]=max(f[j],f[j-ww]+vv); } if(left){ int ww=w[i]*left; int vv=v[i]*left; for(int j=n;j>=ww;j--) f[j]=max(f[j],f[j-ww]+vv); } } int ans=0; for(int i=1;i<=n;i++) ans=max(ans,f[i]); printf("%d\n",ans); } }
【HDU 1059】Dividing
多重背包
给出6种价值不同的物品,每种物品有若干个,问是否能分成总价值相等的两份。首先总价值为奇数时不可。f[i]表示总价值不超过i时能获得的最大价值。判断f[m/2]==m-f[m/2]即可
#include<cstdio> #include<cstring> #include<iostream> using namespace std; const int maxm=120010; int f[maxm]; int n,T=0,m; int a[10]; bool read(){ T++; m=0; for(int i=1;i<=6;i++){ scanf("%d",&a[i]); m+=a[i]*i; } return m==0?0:1; } void work(){ printf("Collection #%d:\n",T); memset(f,0,sizeof(f)); for(int i=1;i<=6;i++){ int left=a[i]; if(left==0)continue; for(int k=1;k<=left;k<<=1){ int t=i*k; left-=k; for(int j=m/2;j>=t;j--) f[j]=max(f[j],f[j-t]+t); } if(left){ int t=i*left; for(int j=m/2;j>=t;j--) f[j]=max(f[j],f[j-t]+t); } } if(f[m/2]==m-f[m/2]) puts("Can be divided."); else puts("Can't be divided."); printf("\n"); } int main(){ while(read()){ work(); } }
【HDU 2844】Coins
多重背包变形
给出一些硬币的价值和数量,问用这些硬币能组合出1~m中的哪些价值。用f[i]表示价值i能否被组合出来即可。
#include<cstdio> #include<cstring> #include<iostream> using namespace std; const int maxn=110; const int maxm=100010; bool f[maxm]; int a[maxn],c[maxn]; int n,m; int main(){ while(scanf("%d%d",&n,&m)&&(n+m)){ for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) scanf("%d",&c[i]); memset(f,0,sizeof(f)); f[0]=1; for(int i=1;i<=n;i++){ int left=c[i]; for(int k=1;k<=left;k<<=1){ int t=a[i]*k; left-=k; for(int j=m;j>=t;j--) f[j]|=f[j-t]; } if(left){ int t=left*a[i]; for(int j=m;j>=t;j--) f[j]|=f[j-t]; } } int ans=0; for(int i=1;i<=m;i++) if(f[i])ans++; printf("%d\n",ans); } }
【HDU 2159】FATE
二维背包
和一维没多大区别。#include<cstdio> #include<cstring> #include<iostream> using namespace std; const int maxn=110; const int maxm=110; int f[maxm][maxm]; int n,m,k,s; int v[maxn],w[maxn]; int main(){ while(~scanf("%d%d%d%d",&n,&m,&k,&s)){ for(int i=1;i<=k;i++) scanf("%d%d",&v[i],&w[i]); memset(f,0,sizeof(f)); for(int i=1;i<=k;i++) for(int j=w[i];j<=m;j++) for(int l=1;l<=s;l++) f[j][l]=max(f[j][l],f[j-w[i]][l-1]+v[i]); if(f[m][s]<n){ puts("-1"); }else{ int cost=m; for(int i=0;i<=m;i++) for(int j=0;j<=s;j++) if(f[i][j]>=n)cost=min(i,cost); printf("%d\n",m-cost); } } }
【HDU 1712】ACboy needs your help
分组背包
ACboy要上M天课,有N种课,每种课上不同天数会获得不同的愉悦度,问ACboy能获得的最大愉悦度。分组背包上就好了。
#include<cstdio> #include<cstring> #include<iostream> using namespace std; const int maxn=110; const int maxm=10010; int n,m; int a[maxn][maxn]; int f[maxm]; 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(f,0,sizeof(f)); for(int i=1;i<=n;i++) for(int j=m;j>=1;j--) for(int k=1;k<=j;k++) f[j]=max(f[j],f[j-k]+a[i][k]); printf("%d\n",f[m]); } }
【HDU 3033】I live sneakers!
分组背包
有一些鞋属于不同组,每种鞋有一个价格和一个价值,现要用不超过M的钱在每组中买至少一种鞋,且每种鞋最多买一次,求所能获得的最大价值。f[i,t]表示枚举到第i组鞋,价格之和为t时的最大价值。f[i,t]=max(f[i,t],f[i-1,t-s[i,j].w]+s[i,j].v,f[i,t-s[i,j].w]+s[i,j].v)
#include<cstdio> #include<cstring> #include<iostream> #include<vector> using namespace std; const int maxn=110; const int maxm=10010; const int maxk=15; struct obj{ int w,v; }; int n,m,k; int f[maxk][maxm]; int max(int a,int b,int c){ return max(a,max(b,c)); } int main(){ while(~scanf("%d%d%d",&n,&m,&k)){ vector<obj> s[maxk]; memset(f,0,sizeof(f)); for(int i=1;i<=n;i++){ int a,b,c; scanf("%d%d%d",&a,&b,&c); s[a].push_back((obj){b,c}); } for(int i=1;i<=k;i++) for(int j=0;j<s[i].size();j++) for(int t=m;t>=s[i][j].w;t--) f[i][t]=max(f[i][t], f[i-1][t-s[i][j].w]+s[i][j].v, f[i][t-s[i][j].w]+s[i][j].v); int ans=0; for(int i=1;i<=m;i++)ans=max(ans,f[k][i]); if(ans==0)puts("Impossible"); else printf("%d\n",ans); } }
【HDU 1561】The more,The Better
树形背包
f[u,m]表示在以i为根的子树中选了包括u在内的m个节点所获得的最大价值f[u,1]=s[u]
f[u,j]=max(f[u,j],f[u,j-k]+f[v,k]) k
#include<cstdio> #include<cstring> #include<iostream> #include<vector> using namespace std; const int maxn=210; int f[maxn][maxn]; int s[maxn]; vector<int> g[maxn]; int n,m; void DFS(int u,int m){ int siz=g[u].size(); f[u][1]=s[u]; for(int i=0;i<siz;i++){ int v=g[u][i]; if(m-1>0)DFS(v,m-1); for(int j=m;j>=2;j--) for(int k=1;k<j;k++)//k<j保证选了u f[u][j]=max(f[u][j],f[u][j-k]+f[v][k]); } } int main(){ while(scanf("%d%d",&n,&m)&&n+m){ for(int i=0;i<=n;i++) g[i].clear(); memset(f,0,sizeof(f)); memset(s,0,sizeof(s)); for(int i=1;i<=n;i++){ int a,b; scanf("%d%d",&a,&b); g[a].push_back(i); s[i]=b; } DFS(0,m+1); printf("%d\n",f[0][m+1]); } }
【HDU 1011】Starship Troppers
树形背包
给出树上每个节点的bugs数量和可获得能量数,现要在节点上驻扎士兵,每个士兵可以消灭20个bugs,节点上bugs少于20时要驻扎一个士兵。现在有m个士兵,问能获得的最大能量为多少。f[i,j]表示以i为根的子树中驻扎j个士兵能获得的最大能量,在树上DP即可
#include<cstdio> #include<cstring> #include<iostream> #include<vector> using namespace std; const int maxn=110; const int maxm=110; int f[maxn][maxm]; int w[maxn],p[maxn]; bool vst[maxn]; int n,m; vector<int> g[maxn]; void DFS(int u){ vst[u]=1; for(int i=w[u];i<=m;i++) f[u][i]=p[u]; int siz=(int)g[u].size(); for(int i=0;i<siz;i++){ int v=g[u][i]; if(vst[v])continue; DFS(v); for(int j=m;j>=w[u];j--) for(int k=1;k<=j-w[u];k++) f[u][j]=max(f[u][j],f[u][j-k]+f[v][k]); } } int main(){ while(scanf("%d%d",&n,&m),n+m>0){ memset(f,0,sizeof(f)); memset(w,0,sizeof(w)); memset(p,0,sizeof(p)); memset(vst,0,sizeof(vst)); for(int i=1;i<=n;i++)g[i].clear(); for(int i=1;i<=n;i++){ scanf("%d%d",&w[i],&p[i]); w[i]=(w[i]+19)/20; } for(int i=1;i<=n-1;i++){ int u,v; scanf("%d%d",&u,&v); g[u].push_back(v); g[v].push_back(u); } if(m==0){ puts("0"); continue; } DFS(1); printf("%d\n",f[1][m]); } }
相关文章推荐
- Java进阶学习第二天——CCS与JS入门
- ASP.Net MVC开发基础学习笔记(4):校验、AJAX与过滤器
- ASP.NET MVC 在控制器中接收视图表单POST过来的数据方法
- MySQL Workbench 6.3.6 在windows下的 安装与使用(一)
- 更新UI操作,Handler与runOnUiThread
- iOS 的旋屏控制技巧
- BZOJ1483: [HNOI2009]梦幻布丁
- Android——自定义动画
- the 7 habits of highly effective people - be proactive
- LayoutInflater的获取与使用
- 【codevs 1282】 约瑟夫问题 【题解】
- mysql存储过程
- listview长按弹出窗popupwindow
- 程序员的一些心得体验!
- ASP.Net MVC开发基础学习笔记(3):Razor视图引擎、控制器与路由机制学习
- C#中的is和as关键字(摘抄)
- HTML 表格表单
- PAT1072. Gas Station (30)
- Linux内核中的常用宏container_of
- 遍历ResultSet,行列要从1开始