zoukankan      html  css  js  c++  java
  • 带权物品背包问题

    也许更好的阅读体验

    (mathcal{Description})
    (n)个物品,每个物品都有一个重量(w_i)和权值(v_i),并给额外(m)个背包,每个背包有一个容量。
    你需要选出若干个物品,并选出同等数量的背包将这些物品装进去,每个背包只能装一个物品,要求每个背包的容量都大于等于其内物品重量.
    接下来,你需要将这些背包从左到右排成一排。如果任意相邻的两个背包,都满足左边背包中物品的重量不超过过右边背包中物品的重量,同时左边背包中物品的价值不超过右边背包中物品的价值。
    问最多可以挑出多少个物品使其满足条件
    (n,mleq 10^5)

    (mathcal{Solution})

    先将物品按照(w)从小到大排序
    然后考虑从大到小将物品放进背包
    (f_i)表示以(i)号物品作为开头最长的序列长度
    考虑第(i)个物品时,找到最小的可以放进去的背包,可以算出有多少个比它大的背包,设为(num)
    (f_i=min(num,max{f_{i+k}}))
    用线段树或者树状数组维护后缀最大值即可
    或者转成从大到小排序维护前缀最大值

    (mathcal{Code})

    /*******************************
    Author:Morning_Glory
    LANG:C++
    Created Time:2019年11月02日 星期六 09时57分32秒
    *******************************/
    #include <cstdio>
    #include <fstream>
    #include <algorithm>
    #include <cstring>
    #define w first
    #define v second
    #define lbt(x) x&-x
    #define reset(x) memset(x,0,sizeof(x))
    using namespace std;
    const int maxn = 200005;
    //{{{cin
    struct IO{
    	template<typename T>
    	IO & operator>>(T&res){
    		res=0;
    		bool flag=false;
    		char ch;
    		while((ch=getchar())>'9'||ch<'0')	flag|=ch=='-';
    		while(ch>='0'&&ch<='9')	res=(res<<1)+(res<<3)+(ch^'0'),ch=getchar();
    		if (flag)	res=~res+1;
    		return *this;
    	}
    }cin;
    //}}}
    int T,n,m,totw,totv;
    int p[maxn],tw[maxn],tv[maxn],c[maxn],f[maxn];
    pair<int,int> a[maxn];
    //{{{init
    void init ()
    {
    	cin>>n;
    	for (int i=1;i<=n;++i)	cin>>a[i].w>>a[i].v,tw[i]=a[i].w,tv[i]=a[i].v;
    	cin>>m;
    	for (int i=1;i<=m;++i)	cin>>p[i],tw[i+n]=p[i];
    
    	sort(tw+1,tw+n+m+1);
    	sort(tv+1,tv+n+1);
    	totw=unique(tw+1,tw+n+m+1)-tw-1;
    	totv=unique(tv+1,tv+n+1)-tv-1;
    
    	for (int i=1;i<=n;++i)
    		a[i].w=lower_bound(tw+1,tw+totw+1,a[i].w)-tw,
    		a[i].v=lower_bound(tv+1,tv+totv+1,a[i].v)-tv;
    
    	sort(a+1,a+n+1);
    
    	for (int i=1;i<=m;++i)	p[i]=lower_bound(tw+1,tw+totw+1,p[i])-tw;
    	sort(p+1,p+m+1);
    
    	while (a[n].w>p[m])	--n;
    }
    //}}}
    //{{{modify
    void modify (int x,int v)
    {
    	for (;x;x-=lbt(x))	c[x]=max(c[x],v);
    }
    //}}}
    //{{{query
    int query (int x)
    {
    	int s=0;
    	for (;x<=totv;x+=lbt(x))	s=max(s,c[x]);
    	return s;
    }
    //}}}
    //{{{solve
    void solve ()
    {
    	reset(f),reset(c);
    	for (int i=n;i;--i){
    		int num=lower_bound(p+1,p+m+1,a[i].w)-p;
    		num=m-num+1;
    		f[a[i].v]=max(f[a[i].v],min(query(a[i].v)+1,num));
    		modify(a[i].v,f[a[i].v]);
    	}
    	int ans=0;
    	for (int i=1;i<=totv;++i)	ans=max(ans,f[i]);
    	printf("%d
    ",ans);
    }
    //}}}
    int main()
    {
    	cin>>T;
    	while (T--){
    		init();
    		solve();
    	}
    	return 0;
    }
    
    

    如有哪里讲得不是很明白或是有错误,欢迎指正
    如您喜欢的话不妨点个赞收藏一下吧

  • 相关阅读:
    使用JavaScript让网页title动起来 TC
    Asp.net获取客户端登录者mac地址 TC
    HTTP错误 500.23Internal Server Error 检测到在集成的托管管道模式下不适用的ASP.NET设置 TC
    上下文字\图片滚动 无JS TC
    SQL语句优化(雷人代码) TC
    js获得url请求参数 TC
    HTTP状态码 TC
    Javascript之表格隔行变色 TC
    C# FTP上传文件报550异常解决方案 TC
    javascript 点击固定数据 隐藏或显示DIV TC
  • 原文地址:https://www.cnblogs.com/Morning-Glory/p/11783238.html
Copyright © 2011-2022 走看看