luogu1056:排座椅:模拟=统计+排序:NOIP2008普及T2

题目链接:该题是luogu试炼场的2-1:T4


试炼场2-1题解包:

2-1 简单模拟  
题号 题目 备注
1003 铺地毯 逆向查找
1067 多项式输出 分段模拟
1540 机器翻译 循环队列
1056 排座椅 统计排序
1328 生活大爆炸版石头剪刀布 暴力模拟
1563 玩具谜题 环形思维

题目大意:

1 在n*m的矩阵里,有k对位置,需要用x条横线和y条竖线,将这k对位置尽可能地切分开:

2 借用原题的图,非常清晰:3对位置,用两竖一横强行切割:

luogu1056:排座椅:模拟=统计+排序:NOIP2008普及T2_第1张图片


解题思路:

1 数据很小,而且是求最优解,所以还是从模拟过程去想;

2 要切尽可能多的对,那就排序咯;

3 然后就结束了。。。。


上代码:

//luogu试炼场2-1:4:1056:排座位 

//解法分析:
//1 统计每行每列需要切割的情况(有人相邻,就可能要切割)
//2 排序,找出最需要切割的行/列
//3 标记前面k行,l列
//4 按原始序号输出 

#include
#include
#include
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;
}

 

你可能感兴趣的:(题解,luogu,题表,大礼包,luogu试炼场)