CF 349 C. Dominoes 贪心吧


C. Dominoes
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

During the break, we decided to relax and play dominoes. Our box with Domino was empty, so we decided to borrow the teacher's dominoes.

The teacher responded instantly at our request. He put nm dominoes on the table as an n × 2m rectangle so that each of the n rows contained m dominoes arranged horizontally. Each half of each domino contained number (0 or 1).

We were taken aback, and the teacher smiled and said: "Consider some arrangement of dominoes in an n × 2m matrix. Let's count for each column of the matrix the sum of numbers in this column. Then among all such sums find the maximum one. Can you rearrange the dominoes in the matrix in such a way that the maximum sum will be minimum possible? Note that it is prohibited to change the orientation of the dominoes, they all need to stay horizontal, nevertheless dominoes are allowed to rotate by 180 degrees. As a reward I will give you all my dominoes".

We got even more taken aback. And while we are wondering what was going on, help us make an optimal matrix of dominoes.

Input

The first line contains integers nm (1 ≤ n, m ≤ 103).

In the next lines there is a description of the teachers' matrix. Each of next n lines contains m dominoes. The description of one domino is two integers (0 or 1), written without a space — the digits on the left and right half of the domino.

Output

Print the resulting matrix of dominoes in the format: n lines, each of them contains m space-separated dominoes.

If there are multiple optimal solutions, print any of them.

Examples
input
2 3
01 11 00
00 01 11
output
11 11 10
00 00 01
input
4 1
11
10
01
00
output
11
10
01
00
Note

Consider the answer for the first sample. There, the maximum sum among all columns equals 1 (the number of columns is 6, and not 3). Obviously, this maximum can't be less than 1, then such matrix is optimal.

Note that the dominoes can be rotated by 180 degrees.



因为关心的是每一列的和,使最大值最小化,我们只需要把01型(和10型是一样的)和11型填上去即可。


所以如果填写时填在某一列的任意一行效果都一样,那么为了方便处理,不妨尽量往上填写。


首先对于11型肯定是要处理的,不妨先处理11型,从上到下,从左到右,依次填下,


我们奇数行从左向右填,偶数行从右向左填,为什么呢,方便底下的一些处理。


11填完了,我们按照这个顺序填01和10,


假如上面一行出界了,随便填10或01


否则,假如上面一行是11,那么随便填10或01


否则,假如上面一行是10,填01


否则,假如上面一行是01,填10,


直到填完一个1的类型,结束。




#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int INF =0x3f3f3f3f;
const int maxn=1000    ;

int a[maxn+5][maxn+5];
char s[2];
int n,m;
int num[4];//0表示两个是0,1表示左1右0,2表示左0右1,3表示11。
void get()
{
    if(s[0]=='0'&&s[1]=='0')
    {
        num[0]++;//全部是0,0类型加1
        return ;
    }
    else if(s[0]=='1'&&s[1]=='1')
    {
        num[3]++;//全部是1,1类型加1
        return ;
    }
    num[1]++;//否则记为1类型,因为1和2其实是一样的,因为可以倒着放。

}


bool in(int &y,int &x)
{
    return 1<=y&&y<=n&&1<=x&&x<=m;
}
void fill(int y,int x)
{
    if(num[1]==0&&num[3]==0)
   {
        a[y][x]=0;
        return;
    }

    if(num[3])
    {
        a[y][x]=3;
        num[3]--;
        return;
    }




    int ty=y-1,tx=x;
    if(!in(ty,tx))
    {
        a[y][x]= 1;
        num[1]--;
        return;
    }
    if(a[ty][tx]==1)
    {
        a[y][x]=2;
        num[1]--;
    }
    else
    {
        a[y][x]=1;
        num[1]--;
    }



}
void work()
{
    for(int i=1;i<=n;i++)
    {
        int j=i%2?1:m;
        int add=i%2?1:-1;
        
        for(  ; 1<=j&&j<=m ;j+=add)
        {
            fill(i,j);

        }

    }


}

void print()
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(j!=1)  putchar(' ');
            if(a[i][j]==0)  printf("00");
            else if(a[i][j]==1) printf("10");
            else if(a[i][j]==2)  printf("01");
            else printf("11");
        }
        putchar('\n');
    }
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        memset(num,0,sizeof num);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                scanf("%s",s);
                get();
            }
        }
        work();
        print();


    }

   return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值