「HDU 5887」Herbs Gathering (背包)
题意:原题在这
给定背包容量和n个物品每个的价值和重量,求能装的物品的最大价值。(采药)
附一组自己出的数据,虽然不够***钻但是查错够用:
5 100
101 200
99 1
1 2
98 20
2 50
做法:(详见行内注释)
做法1:
1. 因为dp解法的复杂度为O(V*N),w[i]和v[i]都在10e9,所以不能dp只能dfs
2. 一种按体积排序的做法:
按照体积由大到小排序,如果后面能取完的就直接取完;
如果后面一直选择最优策略(能获得的最大价值加上已有的)都不好于现在的答案则break;
(参考:https://blog.csdn.net/qq_21057881/article/details/52577874)
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; #define maxn 105 typedef long long ll; int n,k; long long sw[maxn],sv[maxn]; struct node { int w,v; double rate;//物品的性价比 }pack[maxn]; bool cmp(node x,node y) {return x.w>y.w;} long long ans=0; void dfs(int pos,int maxx,ll target) { if(pos==n)//尽量取完 { if(maxx>=pack[pos].w)//如果能装下 ans=max(ans,target+pack[pos].v); else//装不下 ans=max(ans,target); return; } if(sw[pos]<=maxx)//还能装 { ans=max(ans,target+sv[pos]); return; } if(target+sv[pos]<=ans) return;//要搜的+搜到的 都不好于现在,不搜 dfs(pos+1,maxx,target); if(maxx>=pack[pos].w) dfs(pos+1,maxx-pack[pos].w,target+pack[pos].v); } int main() { while(scanf("%d%d",&n,&k)!=EOF) { ans=0; sw[n+1]=0; sv[n+1]=0; for(int i=1;i<=n;i++) { cin>>pack[i].w>>pack[i].v; pack[i].rate = 1.0*pack[i].v/pack[i].w;//计算性价比 } sort(pack+1,pack+n+1,cmp); for(int i=n;i>=1;i--) { sv[i]=sv[i+1]+pack[i].v; sw[i]=sw[i+1]+pack[i].w; } dfs(1,k,0); cout<<ans<<endl; } }
做法2:
1. 先按性价比排序,直接把不能选的去掉,之后搜索的时候若剩下的背包空间都以最高性价比选时不会比已找到的最优解更好时则剪枝
(参考:https://blog.csdn.net/consciousman/article/details/52572702)
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; #define maxn 105 #define INF 0x3f3f3f3f typedef long long LL; int n,k; long long cnt,ans; struct node { long long w,v; double r;//物品的性价比 }pack[maxn]; bool cmp(node x,node y) {return x.r>y.r;} int check(int i,long long sw,long long sv) { for(int j=i; j<cnt && sw<k;j++) { if(pack[j].w+sw<=k) { sw+=pack[j].w; sv+=pack[j].v; } else { sv+=pack[j].r*(k-sw); sw=k; } } return sv>ans; } void dfs(int i,long long sw,long long sv) { ans=max(ans,sv); if(i<cnt && check(i,sw,sv)) { if(sw+pack[i].w<=k) dfs(i+1,sw+pack[i].w,sv+pack[i].v); dfs(i+1,sw,sv); } } int main() { while(scanf("%d %d",&n,&k)!=EOF) { cnt=ans=0; for(int i=1;i<=n;i++) { long long w,v; cin>>w>>v; if(w<=k) { pack[++cnt].w=w; pack[cnt].v=v; pack[cnt].r=(v+0.0)/w; // pack[cnt++]=(node){w, v, (v+0.0)/w}; } } sort(pack+1,pack+1+cnt,cmp); dfs(0,0,0); cout<<ans<<endl; } return 0; }