CF45J Planting Trees

题目描述

Vasya is a Greencode wildlife preservation society proponent. One day he found an empty field nobody owned, divided it into n×mn×m squares and decided to plant a forest there. Vasya will plant nmnm trees of all different heights from 11 to nmnm . For his forest to look more natural he wants any two trees growing in the side neighbouring squares to have the absolute value of difference in heights to be strictly more than 1. Help Vasya: make the plan of the forest planting for which this condition is fulfilled.

输入格式

The first line contains two space-separated integers nn and mm ( 1<=n,m<=1001<=n,m<=100 ) — the number of rows and columns on Vasya's field

输出格式

If there's no solution, print -1. Otherwise, print nn lines containing mm numbers each — the trees' planting plan. In every square of the plan the height of a tree that should be planted on this square should be written. If there are several solutions to that problem, print any of them.

题意翻译

Vasya是greencode野生动物保护协会的支持者。

有一天他找到了一个空地,他把它分成了 n*mn∗m 个方格并决定在上边种出一个森林。Vasya将要种 n*mn∗m 棵高度从 1 到 n*mn∗m 的树,并且高度两两不同。

为了让他的森林看起来更加的自然,他希望任意两颗四联通相邻的树高度差的绝对值严格大于1。请帮助Vasya制定森林的种植计划。无解输出-1,多解输出任意一种方案。

感谢@MloVtry 提供的翻译

输入输出样例

输入 #1

2 3

输出 #1

3 6 2
5 1 4

输入 #2

2 1

输出 #2

-1

思路

四联通相邻,相邻的上下左右四个方向上。

首先是特殊情况,n和m可以互换值,也是一样的。

  • 1x1        1        可以的
  • 1x2        1 2或者2 1      都不可以
  • 1x3        1 3 2或者其他情况     都不可以
  • 1x4        2 4 1 3     可以
  • 1xn       后面的都可以了
  • 2x2       不可以
  • 2x3       可以,样例里面有
  • 2xn       后面的都可以了

不符合的情况是n + m<=4(这里比较巧妙,当1、4的情况时,是可以摆放的,2 4 1 3,但是2 2的情况时,不能够摆放,所以用m*n判断的话,还得多一个判断,但是用m+n就只需要一个判断就可以了),这其中包含了一种特殊情况,n=1,m=1时,是可以的。

if(n==1&&m==1)
{
    printf("1");
    return 0;
}
if(n+m<=4)//这里比较巧妙,当1、4的情况时,是可以摆放的,2 4 1 3,但是2 2的情况时,不能够摆放,所以用m*n判断的话,还得多一个判断,但是用m+n就只需要一个判断就可以了
{
    printf("-1");
    return 0;
}

然后是一般情况,相邻的上下左右方向之间的值相差大于1,可以通过让相邻的数同为奇数或者偶数,然后大小交叉分布,小的从1开始,大的从中间(n*m)/2+1开始就可以了。

判断是放奇数还是偶数那里,原本用的是一个标记来将前一部分的值和后一部分的值交替,但是有些样例上一行的末尾和下一行的开头不需要进行交替,所以出现了错误。例如样例 3 2

for(int i=0;i<n;i++)
{
    for(int j=0;j<m;j++)
    {
        if(flag==0)
        {
            printf("%d ",y++);
            flag=1;
        }
        else
        {
            printf("%d ",x++);
            flag=0;
        }
    }
    printf("\n");
}

代码实现

#include<bits/stdc++.h>
using namespace std;
int main()
{
    long long n,m,a[105][105];
    scanf("%lld %lld",&n,&m);
    if(n==1&&m==1)
    {
        printf("1");
        return 0;
    }
    if(n+m<=4)//这里比较巧妙,当1、4的情况时,是可以摆放的,2 4 1 3,但是2 2的情况时,不能够摆放,所以用m*n判断的话,还得多一个判断,但是用m+n就只需要一个判断就可以了
    {
        printf("-1");
        return 0;
    }
    long long x=1,y=(n*m)/2+1,flag=0;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            if((i+j)%2==0)
            {
                printf("%lld ",y);
                y++;
            }
            else
            {
                printf("%lld ",x);
                x++;
            }
        }
        printf("\n");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值