AtCoder Beginner Contest 109- D - Make Them Even(有意思的题)

D - Make Them Even


Time limit : 2sec / Memory limit : 1024MB

Score : 400 points

Problem Statement

There is a grid of square cells with H horizontal rows and W vertical columns. The cell at the i-th row and the j-th column will be denoted as Cell (i,j).

In Cell (i,j), aij coins are placed.

You can perform the following operation any number of times:

Operation: Choose a cell that was not chosen before and contains one or more coins, then move one of those coins to a vertically or horizontally adjacent cell.

Maximize the number of cells containing an even number of coins.

Constraints

  • All values in input are integers.
  • 1≤H,W≤500
  • 0≤aij≤9

Input

Input is given from Standard Input in the following format:

H W
a11 a12 … a1W
a21 a22 … a2W
:
aH1 aH2 … aHW

Output

Print a sequence of operations that maximizes the number of cells containing an even number of coins, in the following format:

N
y1 x1 y1' x1'
y2 x2 y2' x2'
:
yN xN yN' xN'

That is, in the first line, print an integer N between 0 and H×W (inclusive), representing the number of operations.

In the (i+1)-th line (1≤iN), print four integers yi,xi,yi' and xi' (1≤yi,yi'H and 1≤xi,xi'W), representing the i-th operation. These four integers represents the operation of moving one of the coins placed in Cell (yi,xi) to a vertically or horizontally adjacent cell, (yi',xi').

Note that if the specified operation violates the specification in the problem statement or the output format is invalid, it will result in Wrong Answer.


Sample Input 1

Copy

2 3
1 2 3
0 1 1

Sample Output 1

Copy

3
2 2 2 3
1 1 1 2
1 3 1 2

Every cell contains an even number of coins after the following sequence of operations:

  • Move the coin in Cell (2,2) to Cell (2,3).
  • Move the coin in Cell (1,1) to Cell (1,2).
  • Move one of the coins in Cell (1,3) to Cell (1,2).

    题解:可以从不硬币为0的网格中移动一块硬币到上下左右相邻的一个网格中,是的网格中硬币为偶数的网格尽可能的多,求移动的步数和移动的过程。这题不难但是我觉得很有意思。直接从从0,0开始遍历如果当前网格为奇数或者小于0就从接下来的网格中移动一块硬币,当达到水平最后一格下一次就从最后一格开始,跑到第一格下一次就从第一格开始,知道遍历完。用栈存储移动过程,但是最后要去除最后几个网格为-1的格子并且要使栈的大小为偶数。移动的步数就是栈的大小除2,然后在每次从栈中取两个打印就好了。


    #include<bits/stdc++.h>
    using namespace std;
    struct  Point
    {
        int x,y;
        Point(int x,int y):x(x),y(y) {}
    };
    int h,w,grid[1000][1000];
    int main()
    {
        cin>>h>>w;
        stack<Point> sta;
        int ans=0;
        for(int i=1; i<=h; i++)
        {
            for(int j=1; j<=w; j++)
                cin>>grid[i][j];
        }
        for(int i=1; i<=h; i++)
        {
            if(i%2!=0)
            {
                for(int j=1; j<=w; j++)
                {
                    if(grid[i][j]%2!=0&&j<w)
                    {
                        grid[i][j+1]-=1;
                        sta.push(Point(i,j));
                        sta.push(Point(i,j+1));
                    }
                    else if(grid[i][j]%2!=0&&j==w)
                    {
                        grid[i+1][j]-=1;
                        sta.push(Point(i,j));
                        sta.push(Point(i+1,j));
                    }
                }
            }
            else
            {
                for(int j=w; j>0; j--)
                {
                    if(grid[i][j]%2!=0&&j>1)
                    {
                        grid[i][j-1]-=1;
                        sta.push(Point(i,j));
                        sta.push(Point(i,j-1));
                    }
                    else if(grid[i][j]%2!=0&&j==1)
                    {
                        grid[i+1][j]-=1;
                        sta.push(Point(i,j));
                        sta.push(Point(i+1,j));
                    }
                }
            }
        }
        while(!sta.empty()&&grid[sta.top().x][sta.top().y]<0)
        {
            sta.pop();
        }
        if(sta.size()%2!=0)
            sta.pop();
        cout<<sta.size()/2<<endl;
        while(!sta.empty())
        {
            cout<<sta.top().x<<" "<<sta.top().y<<" ";
            sta.pop();
            cout<<sta.top().x<<" "<<sta.top().y<<endl;
            sta.pop();
        }
        return 0;
    }
    

     

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值