• 【LOJ6254】最优卡组 堆(模拟搜索)


    【LOJ6254】最优卡组

    题面

    题解:常用的用堆模拟搜索套路(当然也可以二分)。先将每个卡包里的卡从大到小排序,然后将所有卡包按(最大值-次大值)从小到大排序,并提前处理掉只有一张卡的卡包。

    我们将状态用一个四元组(val,x,y,z)表示,意思是当前所有卡的和是val,我们人为的选择了前x包卡(后n-x包卡都选的是最大值),第x包卡选择了第y张,z表示当前状态是否是由2或3转移得来的,具体含义见下面(设计的非常巧妙,一开始自己想了几个策略都有遗漏)。

    那么这个状态可以扩展到如下几种状态:

    1.如果y<cx,则我们可以选择卡包x的下一张卡,即扩展到(val+...,x,y+1,0)
    2.如果x<n(已经处理掉只有一张卡的卡包了),则我们可以选择下一割卡包的第二张卡,即拓展到(val+...,x+1,2,1)
    3.如果x<n且z=1,我们可以撤销这割卡包的第二张卡,选择下一个卡包的第二张卡,即拓展到(val+...,x+1,2,1)

    容易证明这样能不重不漏的,从大到小的枚举到所有状态。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <queue>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const int maxn=300010;
    struct node
    {
    	ll val;
    	int x,y;
    	bool z;
    	node() {}
    	node(ll a,int b,int c,bool d) {val=a,x=b,y=c,z=d;}
    	bool operator < (const node &a) const
    	{
    		return val<a.val;
    	}
    };
    priority_queue<node> q;
    int n,m;
    int p[maxn],c[maxn];
    vector<ll> v[maxn];
    inline char nc()
    {
    	static char buf[100000],*p1=buf,*p2=buf;
    	return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    }
    inline ll rd()
    {
    	ll ret=0;	char gc=nc();
    	while(!isdigit(gc))	gc=nc();
    	while(isdigit(gc))	ret=ret*10+(gc^'0'),gc=nc();
    	return ret;
    }
    char puf[100000],*p3=puf;
    inline void ps(const char &x)
    {
    	if(p3==puf+100000)	fwrite(puf,1,100000,stdout),p3=puf;
    	*p3++=x;
    }
    inline void flush()
    {
    	fwrite(puf,1,p3-puf,stdout);
    }
    inline void wt(ll x)
    {
    	static char sta[20];
    	int top=0;
    	if(!x)	ps('0');
    	while(x)	sta[++top]=(x%10)^'0',x/=10;
    	while(top)	ps(sta[top--]);
    }
    bool cmp1(const int &a,const int &b)
    {
    	return a>b;
    }
    bool cmp2(const int &a,const int &b)
    {
    	if(c[a]==1||c[b]==1)	return c[a]!=1;
    	return v[a][0]-v[a][1]<v[b][0]-v[b][1];
    }
    int main()
    {
    	//freopen("loj6254.in","r",stdin);
    	n=rd(),m=rd();
    	int i,j,a,b;
    	node x=node(0,1,0,0);
    	for(i=1;i<=n;i++)
    	{
    		v[i].clear(),c[i]=rd(),p[i]=i;
    		for(j=0;j<c[i];j++)	v[i].push_back(rd());
    		sort(v[i].begin(),v[i].end(),cmp1);
    		x.val+=v[i][0];
    	}
    	sort(p+1,p+n+1,cmp2);
    	while(c[p[n]]==1)	n--;
    	q.push(x);
    	while(m--)
    	{
    		x=q.top(),q.pop(),a=x.x,b=x.y;
    		//printf("%lld%c",x.val,!m?'
    ':' ');
    		wt(x.val),ps(!m?'
    ':' ');
    		if(b+1<c[p[a]])	q.push(node(x.val-v[p[a]][b]+v[p[a]][b+1],a,b+1,0));
    		if(a<n)	q.push(node(x.val-v[p[a+1]][0]+v[p[a+1]][1],a+1,1,1));
    		if(a<n&&x.z)	q.push(node(x.val-v[p[a]][1]+v[p[a]][0]-v[p[a+1]][0]+v[p[a+1]][1],a+1,1,1));
    	}
    	flush();
    	return 0;
    }
  • 相关阅读:
    mybatis绑定错误-- Invalid bound statement (not found)
    JAVA MyBatis配置文件用properties引入外部配置文件
    JAVA错误提示:The operation is not applicable to the current selection.Select a field which is not declared as type variable or a type that declares such fields.
    MySql5.5安装步骤及MySql_Front视图配置
    Failed to load AppCompat ActionBar with unknown error
    android:整理drawable(余下的)(三)
    android:整理drawable(shapdrawable)(二)
    与drawable的较量(一)
    gradle与android studio 关系及gradle配置
    键盘优雅弹出与ios光标乱飘解决方案
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/8098295.html
Copyright © 2020-2023  润新知