AOJ 完全背包 数量少体积大价值小版本 dp+贪心

DPL_1_I

n和v只有50 但体积很大。直接贪心明显过不了一些特殊的数据。

考虑答案的构造 一堆大的+令一堆大的+...+几个数量少的。

前面的肯定是按照贪心选的 对于数量少的可以直接dp。

这里dp的阈值为50 这个阈值越大越精确 对于本题取50就可以(虽然不太明白这个阈值到底怎么算。

也就是先利用价值进行dp 再贪心。减小时间和代码复杂度 使用二进制分组做多重背包。

//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000000000000ll
#define inf 1000000001
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(p,n,i) for(int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define pii pair<int,int>
#define mk make_pair
#define P 1000000007ll
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-10
#define sq sqrt
#define S second
#define F first
#define mod 998244353
#define v(x) t[x].v
#define w(x) t[x].w
#define m(x) t[x].m
#define mx2(x) t[x].mx2
#define max(x,y) ((x)<(y)?y:x)
using namespace std;
char *fs,*ft,buf[1<<15];
inline char gc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
    return x*f;
}
const int MAXN=510,N=50*50*51;
int n,W;
ll f[N],ans;
struct wy
{
	ll v,w,m;
}t[MAXN];
inline int cmp(wy a,wy b){return a.v*b.w>b.v*a.w;}
int main()
{
	freopen("1.in","r",stdin);
	n=read();W=read();
	rep(1,n,i)v(i)=read(),w(i)=read(),m(i)=read();
	
	f[0]=0;int C=50*50*50;
	rep(1,C,i)f[i]=INF;
	
	rep(1,n,i)
	{
		int ww=min(m(i),50ll);
		m(i)-=ww;
		for(int k=1;;k=k<<1)
		{
			if(k>ww)break;
			for(int j=C;j>=k*v(i);--j)f[j]=min(f[j],f[j-k*v(i)]+k*w(i));
			ww-=k;
		}
		for(int j=C;j>=ww*v(i);--j)f[j]=min(f[j],f[j-ww*v(i)]+ww*w(i));
	}
	
	sort(t+1,t+1+n,cmp);
	
	rep(0,C,i)
	{
		if(f[i]==INF||f[i]>W)continue;
		ans=max(ans,i);
		int W1=W-f[i];
		ll ANS=i;
		rep(1,n,j)
		{
			int cc=min(W1/w(j),m(j));
			ANS+=cc*v(j);
			W1-=cc*w(j);
		}
		ans=max(ans,ANS);
	}
	
	printf("%lld\n",ans);
	return 0;
}

posted @ 2022-09-01 19:01  chdy  阅读(71)  评论(0编辑  收藏  举报