题解 P1056 【排座椅】
由于题中多次提到“最优方案”与“最好的”等词语,很容易想到这题要使用贪心。
由题可知,我们要尽量多的将交头接耳的同学隔开,而题中已给出过道的行数与列数,因此我们只需要找到隔开交头接耳同学数量最多的K条横向的通道和L条纵向的通道。
操作步骤如下
- 用结构体记录相应的量(方便后期操作)。
- 在读入同学坐标时,记录每条通道能隔开的数量。(若xp,则过道为(y+q)/2;若yq,则过道为(x+p)/2)
- 排序,输出。
代码:
#include <iostream>
#include <algorithm>
using namespace std;
struct con{ //定义结构体
int x,y; //同学1坐标
int p,q; //同学2坐标
int b,c; //b为横向通道数,c为纵向通道数
int pp; //编号
}a[2200];
int comp1(const con &x,const con &y) //排序函数(将横向通道数目从大到小排)
{
return x.b>y.b;
}
int comp2(const con &x,const con &y) //排序函数(将纵向通道数目从大到小排)
{
return x.c>y.c;
}
int comp3(const con &x,const con &y) //排序函数(将编号从小到大排)
{
return x.pp<y.pp;
}
int m,n,k,l,d;
int main()
{
int i,j;
cin>>m>>n>>k>>l>>d; //输入,如题。
for(i=1;i<=2200;i++) a[i].pp=i; //编号。
for(i=1;i<=d;i++)
{
cin>>a[i].x>>a[i].y>>a[i].p>>a[i].q;
if(a[i].q==a[i].y) a[(a[i].p+a[i].x)/2].b++;
else a[(a[i].q+a[i].y)/2].c++; //记录隔开同学数目,状态。
}
sort(a+1,a+1+1000,comp1); //将隔开同学数从大到小排。
sort(a+1,a+1+k,comp3); //记得编号要从小到大输出
for(i=1;i<=k;i++) cout<<a[i].pp<<" ";
cout<<endl;
sort(a+1,a+1+1000,comp2); //同上
sort(a+1,a+1+l,comp3); //同上
for(i=1;i<=l;i++) cout<<a[i].pp<<" ";
return 0;
}

浙公网安备 33010602011771号