最优卡组
题解
我们可以先考虑堆模拟搜索。可以先将卡包内部排序,再用卡包的最大与次大排序。
我们用一个四元组(val,x,y,z)存储状态,val即当前的卡能量值,选择前x包卡,第x包选的是第y张牌。z表示是否它由下方的第2,3情况转来。
有如下几种情况:
1.当,则我们可选的情况有
2.当,则我们可选的情况有
3.当,则我们可选的情况有
可以证明这样枚举不会重复或漏掉。可惜我不会
源码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<stack>
#include<vector>
#include<queue>
#include<cstdlib>
#define node ming
using namespace std;
typedef long long LL;
const LL INF=0x3f3f3f3f;
const LL MAXN=3000010;
template<typename _T>
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++;
}
LL rd()
{
LL ret=0;
char gc=getchar();
while(!isdigit(gc)) gc=getchar();
while(isdigit(gc)) ret=ret*10+(gc^'0'),gc=getchar();
return ret;
}
struct ming
{
LL val;
int x,y;
bool z;
ming(){}
ming(LL V,int X,int Y,bool Z){val=V;x=X;y=Y;z=Z;}
bool operator < (const ming &a)const
{
return val<a.val;
}
};
priority_queue<ming> q;
int n,m;
int p[MAXN],c[MAXN];
vector<LL> v[MAXN];
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];
}
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--]);
}
int main()
{
n=rd();m=rd();
int i,j,a,b;
ming x=ming(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;
wt(x.val),ps(!m?'\n':' ');
if(b+1<c[p[a]]) q.push(ming(x.val-v[p[a]][b]+v[p[a]][b+1],a,b+1,0));
if(a<n) q.push(ming(x.val-v[p[a+1]][0]+v[p[a+1]][1],a+1,1,1));
if(a<n&&x.z) q.push(ming(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;
}