题解 P3254 【圆桌问题】

philosopherchang

2018-12-15 20:53:44

Solution

我也来发贪心。 把桌子大小和队伍大小从大到小排个序,然后一个一个的坐座位,最后在按照队伍编号再排回来。证明的话有人说不会,其实很简单,队伍越大越不容易满足,所以我们先让它满足,一个桌子一次只安一个人,满人的话就跳过那张桌子往后排,如果说在排座次的过程中,一直有一个人(也可能是多个)没地坐,也就是说一直到最后一张桌子还是满人,那么就可以巧妙地输出0了。 然后就是,蒟蒻不会vector,所以这是一个不用vector的题解,比[沛霖](https://www.luogu.org/space/show?uid=48455)dalao的代码量大,但我感觉应该更容易懂。 然后上代码 ```cpp #include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; int n,m,ll; struct node{ int num,wei,xy[1001],hao;//xy是每个人做的桌子编号 }a[1501];//我发现按着题目开数组最后一个点RE了,所以就大了点。 struct edge{//这个真的不是建边,是想不出结构体名称了。 int num1,shu,wi; }b[3001]; bool c[3001];//判断桌子是否坐满 int cmp(node x,node y) { return x.num>y.num; } int cmp2(edge x,edge y) { return x.num1>y.num1; } int cmp1(node x,node y) { return x.wei<y.wei; } void dfs() { for(int i=1;i<=m;i++) { int cnt=0; for(int j=1;j<=n;j++) { if(j==n&&c[j]==1)//如果扫到最后一张桌子发现桌子还是满的,就输出0,在void里没法直接输出,只能限定义一个ll变量。 { ll=1; return ; } if(c[j]==0) { a[i].num--;//此队伍中还剩下的人数 cnt++; a[i].xy[cnt]=b[j].wi; b[j].shu++; if(b[j].shu==b[j].num1) { c[j]=1; } } if(a[i].num==0) { a[i].hao=cnt;//记录下a[i].xy的长度,因为原来定义的num已经被我们减去了。 break; } } } return ; } void print() { sort(a+1,a+m+1,cmp1); cout<<1<<endl; for(int i=1;i<=m;i++) { for(int j=1;j<=a[i].hao;j++) { cout<<a[i].xy[j]<<" "; } cout<<endl; } } int main() { cin>>m>>n; for(int i=1;i<=m;i++) { cin>>a[i].num; a[i].wei=i;//wei是队伍编号 } for(int i=1;i<=n;i++) { cin>>b[i].num1; b[i].wi=i;wi是桌子编号 } sort(a+1,a+n+1,cmp); sort(b+1,b+n+1,cmp2); dfs();//实在想不出函数名了才起的dfs。 if(ll==1) { cout<<0; return 0; } print(); return 0; } ```