〖NOIP2008P〗排座椅

描述

上课的时候总会有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情。不过,班主任小雪发现了一些有趣的现象,当同学们的座次确定下来 之后,只有有限的D对同学上课时会交头接耳。同学们在教室中坐成了M行N列,坐在第i行第j列的同学的位置是(i,j),为了方便同学们进出,在教室中设 置了K条横向的通道,L条纵向的通道。于是,聪明的小雪想到了一个办法,或许可以减少上课时学生交头接耳的问题:她打算重新摆放桌椅,改变同学们桌椅间通 道的位置,因为如果一条通道隔开了两个会交头接耳的同学,那么他们就不会交头接耳了。

请你帮忙给小雪编写一个程序,给出最好的通道划分方案。在该方案下,上课时交头接耳的学生的对数最少。

 

明显贪心,因为我们要在有限的改变次数内做出最好的选择。

怎么样才能算是最好选择?

如果我们要在行之间隔出一条通道,那么我们就应该选择两行之间交头接耳人数最多的,在这里开一条通道;

如果我们要在列之间隔出一条通道,那么我们就应该选择两列之间交头接耳人数最多的,在这里开一条通道;

于是我们需要对每两行和每两列之间交头接耳的人做出排序,并且记录下他们的位置,然后进行选择。

void readp(){
     cin>>n>>m>>nk>>mk>>d;
     for(int i=1;i<n;i++) h[i].id=i;
     for(int i=1;i<m;i++) l[i].id=i;
     int x1,y1,x2,y2;
     while(d--){
           cin>>x1>>y1>>x2>>y2;
           if(x1==x2) {
              if(y1<y2) l[y1].s++;
              else l[y2].s++;
              }
              else {
                   if(x1<x2) h[x1].s++;
                   else h[x2].s++;
                  }
           }
     }

读入并且记录下每行每列交头接耳的人数,记录下行号和列号

void work(){
     sort(h+1,h+n,cmp);
     sort(l+1,l+m,cmp);
     sort(h+1,h+nk+1,cmp1);
     sort(l+1,l+mk+1,cmp1);
     for(int i=1;i<=nk;i++) cout<<h[i].id<<" ";
     cout<<endl;
     for(int i=1;i<=mk;i++) cout<<l[i].id<<" ";
     cout<<endl;
}

 把人数排序,并且由于输出也需要排序,所以我们还要使用函数对结构体进行排序。

bool cmp(node p,node q){
     return p.s>q.s;
}

bool cmp1(node p,node q){
     return p.id<q.id;
}

 

 posted on 2016-10-15 23:13  Copen  阅读(250)  评论(0编辑  收藏  举报