题目链接:该题是luogu试炼场的2-1:T4
试炼场2-1题解包:
2-1 | 简单模拟 | |
题号 | 题目 | 备注 |
1003 | 铺地毯 | 逆向查找 |
1067 | 多项式输出 | 分段模拟 |
1540 | 机器翻译 | 循环队列 |
1056 | 排座椅 | 统计排序 |
1328 | 生活大爆炸版石头剪刀布 | 暴力模拟 |
1563 | 玩具谜题 | 环形思维 |
题目大意:
1 在n*m的矩阵里,有k对位置,需要用x条横线和y条竖线,将这k对位置尽可能地切分开:
2 借用原题的图,非常清晰:3对位置,用两竖一横强行切割:
解题思路:
1 数据很小,而且是求最优解,所以还是从模拟过程去想;
2 要切尽可能多的对,那就排序咯;
3 然后就结束了。。。。
上代码:
//luogu试炼场2-1:4:1056:排座位
//解法分析:
//1 统计每行每列需要切割的情况(有人相邻,就可能要切割)
//2 排序,找出最需要切割的行/列
//3 标记前面k行,l列
//4 按原始序号输出
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int mx=2005;
int n,m,k,l,d;
struct nod{int s,o;}ha[mx],le[mx];
int xx[mx],yy[mx];
bool cmp(nod x,nod y) { return x.s>y.s; }
int main()
{
memset(xx,0,sizeof(xx));
memset(yy,0,sizeof(yy));
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++) { ha[i].o=i;ha[i].s=0; }
for(int i=1;i<=m;i++) { le[i].o=i;le[i].s=0; }
scanf("%d %d",&k,&l);
scanf("%d",&d);
int x,y,a,b;
for(int i=1;i<=d;i++)
{
scanf("%d %d",&x,&y);
scanf("%d %d",&a,&b);
if(x==a)//同行
{
if(y>b) le[b].s++;
else if(b>y) le[y].s++;
}
else if(y==b)//同列
{
if(x>a) ha[a].s++;
else if(a>x) ha[x].s++;
}
}
sort(ha+1,ha+1+n,cmp);
sort(le+1,le+1+m,cmp);
for(int i=1;i<=k;i++) xx[ha[i].o]=1;
for(int i=1;i<=l;i++) yy[le[i].o]=1;
for(int i=1;i<=n;i++) if(xx[i]) printf("%d ",i);printf("\n");
for(int i=1;i<=m;i++) if(yy[i]) printf("%d ",i);printf("\n");
return 0;
}