https://www.luogu.org/problem/show?pid=1056

题目描述

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

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

输入输出格式

输入格式:

输入的第一行,有5个用空格隔开的整数,分别是M,N,K,L,D(2<=N,M<=1000,0<=K<M,0<=L<N,D<=2000)。

接下来的D行,每行有4个用空格隔开的整数。第i行的4个整数Xi,Yi,Pi,Qi,表示坐在位置(Xi,Yi)与(Pi,Qi)的两个同学会交头接耳(输入保证他们前后相邻或者左右相邻)。

输入数据保证最优方案的唯一性。

输出格式:

输出共两行。

第一行包含K个整数,a1,a2……aK,表示第a1行和a1+1行之间、第a2行和a2+1行之间、…、第aK行和第aK+1行之间要开辟通道,其中ai< ai+1,每两个整数之间用空格隔开(行尾没有空格)。

第二行包含L个整数,b1,b2……bL,表示第b1列和b1+1列之间、第b2列和b2+1列之间、…、第bL列和第bL+1列之间要开辟通道,其中bi< bi+1,每两个整数之间用空格隔开(列尾没有空格)。

输入输出样例

输入样例#1:

4 5 1 2 3
4 2 4 3
2 3 3 3
2 5 2 4
输出样例#1:

2
2 4

说明

上图中用符号*、※、+标出了3对会交头接耳的学生的位置,图中3条粗线的位置表示通道,图示的通道划分方案是唯一的最佳方案。

题目中有一行“输入保证最优解唯一”

因此考虑贪心法:选择交头接耳人数最多的过道

程序实时处理交头接耳的人,判断他们“横跨”第几行/第几列,给相应的行/列交头接耳人数+1

然后选出人最多的行列(可以放心这么做否则解就是不唯一的矛盾),排序后输出即可

 1 # include <stdio.h>
2 # define min(x,y) (x<y?x:y)
3 int main()
4 {
5 short M,N,row[999]={0},column[999]={0}, //教室里的座位共有M行N列(2≤M,N≤1000)
6 K,L,D,i,X[2000],Y[2000],P[2000],Q[2000]; //需要开辟K条横向通道和L条纵向通道
7 scanf("%hd %hd %hd %hd %hd",&M,&N,&K,&L,&D); //用以最大限度地隔离D对相邻的爱说话的同学
8 void passageway(short[],short,short); //函数passageway用于给出开辟通道的最优方案
9 for(i=0;i<D;i++) //每对相邻的爱说话的两个同学
10 scanf("%hi%hi%hi%hi",&X[i],&Y[i],&P[i],&Q[i]); //分别位于第X行第Y列和第P行第Q列
11 while(i--) //对于每对相邻的爱说话的两个同学
12 if(X[i]==P[i]) //当他们位于同一行的相邻列时
13 column[min(Y[i],Q[i])-1]++; //可以考虑在他们中间开辟一条纵向通道
14 else //当他们位于同一列的相邻行时
15 row[min(X[i],P[i])-1]++; //可以考虑在他们中间开辟一条横向通道
16 passageway(row,K,M); //输出需要开辟的K条横向通道的位置
17 passageway(column,L,N); //输出需要开辟的L条纵向通道的位置
18 return 0;
19 }
20 void passageway(short _[],short way,short all) //way为要求开辟的通道数,all为座位总行/列数
21 {
22 short t,passage=0,limit=0; //limit为开辟通道所需的爱说话同学的对数下限
23 while(passage!=way) //当下限limit设定不合适时
24 for(t=passage=0,limit++;t<all;t++) //增加下限limit,重新计算此时开辟的通道数
25 passage+=_[t]>=limit; //使其恰好等于要求开辟的通道数
26 for(t=0;way;t++) //当下限limit设定合适时
27 if(_[t]>=limit)
28 printf(--way?"%d ":"%d",t+1); //输出开辟的各条通道的位置
29 puts(""); //换行
30 }
31
32 //说明:0≤K<M,0≤L<N,D≤2000。对于输出的每个数a,表示在第a行/列和第(a+1)行/列之间开辟通道。

最普通最好用的蒟蒻方法。

使用结构体标记x,y轴,然后在读入每一对同学时,如果他们x轴相同就放在一个组,y轴相同放在另一个组,然后把对应的数组的值+1。

这样我们使用一个贪心的思路:对于x轴和y轴,某一条无论怎么分割对其他的分割线都没有影响。

因此,只需分别对读入后这两个结构体的值降序排序,取前k和前l个的位置坐标输出即可,可以证明这是最优的思路。

要注意有坑。在找出我们需要的位置时,别忘了对位置再排个序输出,不然WA声一片。

具体见代码吧,强迫症使然的c++选手。。。

快捷而简约的STL是个好东西。

 1 #include<iostream>
2 #include<algorithm>
3 using namespace std;
4 struct seq{int i,val;}a[1010],b[1010];
5 int n,m,k,l,d,as[1010],bs[1010];
6 int x1,y1,x2,y2;
7 bool comp(seq,seq);
8 int main()
9 {
10 cin>>n>>m>>k>>l>>d;
11 for(int z=1;z<=1010;z++)
12 a[z].i=b[z].i=z;
13 for(int z=1;z<=d;z++)
14 {
15 cin>>x1>>y1>>x2>>y2;
16 if(x1==x2)
17 b[min(y1,y2)].val++;
18 if(y1==y2)
19 a[min(x1,x2)].val++;
20
21 }//对输入的数据处理,计算分割各个位置可以获得的值,min是为了取两个坐标的最小(反正差值是1)以方便累计
22
23 sort(a+1,a+1001,comp);
24 sort(b+1,b+1001,comp);
25 for(int z=1;z<=k;z++)
26 as[z]=a[z].i;
27 for(int z=1;z<=l;z++)
28 bs[z]=b[z].i;//对x,y轴的两个结构体的值排序并转移到记录位置的数组
29 sort(as+1,as+k+1);
30 sort(bs+1,bs+l+1);
31 for(int z=1;z<=k;z++)
32 cout<<as[z]<<" ";
33 cout<<endl;
34 for(int z=1;z<=l;z++)
35 cout<<bs[z]<<" ";
36 cout<<endl;//对两个记录位置的数组进行升序排序然后输出
37 return 0;
38 }
39 bool comp(seq i,seq j){return i.val>j.val;}

利用唯一答案的条件:

#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
int main()
{
int m,n,k,l,d;
int s1[10001],s2[10001];
fill(s1,s1+10001,0);
fill(s2,s2+10001,0);
cin>>m>>n>>k>>l>>d;
int max1=0,max2=0;
for (int i=1;i<=d;i++)
{
int a1,b1,c1,d1;
cin>>a1>>b1>>c1>>d1;
if (a1==c1)
{
if (b1<d1) s2[b1]++;
else s2[d1]++;
}
else
{
if (a1<c1) s1[a1]++;
else s1[c1]++;
}
}
int a=0,b=0;
for (int i=1;i<=10000;i++) if (s1[i]>=max1) max1=s1[i];
for (int i=1;i<=10000;i++) if (s2[i]>=max2) max2=s2[i];
while (a<k)
{
for (int i=1;i<=10000;i++) if (s1[i]==max1) a++;
max1--;
}
max1++;
while (b<l)
{
for (int i=1;i<=10000;i++) if (s2[i]==max2) b++;
max2--;
}
max2++;
for (int i=1;i<=10000;i++) if (s1[i]>=max1) cout<<i<<" ";
cout<<endl;
for (int i=1;i<=10000;i++) if (s2[i]>=max2) cout<<i<<" ";
cout<<endl;
return 0;
}

洛谷P1056——排座椅(模拟,贪心,排序)的更多相关文章

  1. 洛谷 P1056 排座椅【贪心/结构体排序】

    题目描述 上课的时候总会有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情.不过,班主任小雪发现了一些有趣的现象,当同学们的座次确定下来之后,只有有限的D对同学上课时会交头接耳.同学 ...

  2. 洛谷P1056 排座椅

    洛谷P1056 排座椅 洛谷传送门 题目描述 上课的时候总会有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情.不过,班主任小雪发现了一些有趣的现象,当同学们的座次确定下来之后,只有 ...

  3. 洛谷 P1056 排座椅 题解

    P1056 排座椅 题目描述 上课的时候总会有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情.不过,班主任小雪发现了一些有趣的现象,当同学们的座次确定下来之后,只有有限的 \(D\ ...

  4. 洛谷 P1056 排座椅

    P1056 排座椅 题目描述 上课的时候总会有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情.不过,班主任小雪发现了一些有趣的现象,当同学们的座次确定下来之后,只有有限的D对同学上 ...

  5. 洛谷 P1056 排座椅 桶排序

    桶排序大法好! 每次一看到这种范围小的题,本萌新就想用桶排. 因为题目中的m,n都小于1000,我们就可以定义两个1000的数组,表示每一行或每一列可以隔开几对讲话的童鞋. 然后再定义两个1000的数 ...

  6. 洛谷——P1056 排座椅

    https://www.luogu.org/problem/show?pid=1056#sub 题目描述 上课的时候总会有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情.不过,班主 ...

  7. java实现 洛谷 P1056 排座椅

    import java.util.Arrays; import java.util.Map.Entry; import java.util.Scanner; import java.util.Tree ...

  8. 洛谷P1080(NOIP2012)国王游戏——贪心排序与高精度

    题目:https://www.luogu.org/problemnew/show/P1080 排序方法的确定,只需任取两个人,通过比较与推导,可以得出ai*bi小的人排在前面: 高精度写的时候犯了些细 ...

  9. [洛谷P3809]【模板】后缀排序

    [洛谷P3809][模板]后缀排序 题目大意: 对于给定的长度为\(n(n\le10^6)\)的字符串求后缀数组\(sa[i]\). 思路: 倍增+快排构造后缀数组.代码参考<挑战程序设计竞赛& ...

随机推荐

  1. tomcat 配置http跳转https

    web.xml增加配置 <security-constraint> <web-resource-collection > <web-resource-name >S ...

  2. 【笔记】Bagging和Pasting以及oob(Out-of-Bag)

    Bagging和Pasting以及oob(Out-of-Bag) Bagging和Pasting 前面讲到soft voting classifier和hard voting classifier两个 ...

  3. Java Lambda 表达式源码分析

    基本概念 Lambda 表达式 函数式接口 方法引用 深入实现原理 字节码 为什么不使用匿名内部类? invokedynamic 总结 参考链接 GitHub 项目 Lambda 表达式是什么?JVM ...

  4. 配置VRRP的多备份组

    实验拓扑和端口IP见上一个博客 实验步骤: 1.继续创建虚拟组2 2. 2. 查看 3.验证: PC1 PC2 PC1通过R2,PC2通过R3访问外网 二.验证VRRP的抢占特性 可以看到,即使R2的 ...

  5. Spring中的@Transactional必须要了解的概念

    spring中的@Transactional基于动态代理的机制,提供了一种透明的事务管理机制,方便快捷解决在开发中碰到的问题. 一般使用是通过如下代码对方法或接口或类注释: 1 @Transactio ...

  6. NPM使用方法

    什么是npm npm是nodejs的包管理器,在当今工程化前端开发过程中,npm包起着举足轻重的作用. 安装npm 作为nodejs的包管理器,npm随着nodejs一起安装的.通常情况下,当我们安装 ...

  7. redis和memecache有什么区别?

    1.memcache所有值均是简单地字符串,redis有复杂的数据类型. 2.memcache不支持数据持久化,redis支持数据持久化. 3.redis速度比memcache快,redis构建了自己 ...

  8. docker-compose部署mysql,redis,rabbitmq

    version: '3' services: mysql: image: mysql:5.7.31 container_name: mysql restart: always command: --c ...

  9. SpringBoot和mybatis整合报错:Caused by: org.apache.ibatis.builder.BuilderException: Error creating document instance. Cause: org.xml.sax.SAXParseException; lineNumber: 152; columnNumber: 10; 元素类型为 "mapper"

    很明显,报错是xml有问题,于是去检查,发现: 由于粗心,保存的时候,按的太频繁,多按了个s在里面,导致启动报错!

  10. WPF以鼠标当前位置进行缩放

    <Window x:Class="ImageViewer.MainWindow" xmlns="http://schemas.microsoft.com/winfx ...