Codeforces(#783.div2)a题

原题链接链接

题目大意:在N*M的网格上,从(1,1)开始向四个方向移动,每个方向只能移动一次,求到达(N,M)最小步数。

题解:这些移动是对称的,因此我们可以假设n≥mn≥m.如果没有解决方案,如果m=1m=1n≥3n≥3,因为一个人只能上下移动,但需要连续两次向下移动才能达到(n,1)(n,1).否则,就有解决方案。                                                 

一个人至少应该向下移动n−1n−1时间,并且禁止连续两次这样做,所以另一个n−2n−2移动是必要的(11在每对之间)。所以至少n−1+n−2=2⋅n−3n−1+n−2=2⋅n−3需要移动。如果n+mn+m是偶数,然后又是一个,因为奇偶校验a+ba+b每次移动后都会发生变化,并且奇偶校验甚至在第一次移动之前和最后一次移动之后,因此移动总数应该是偶数。

该下限有一个构造:交替向下和向右移动。到达后mm-第 0 列,重复以下移动顺序:向下、向左、向下、向右。有了这个44移动长序列,可以向下移动两次。

  因此,我们将达到(n−1,米)(n−1,m),那么需要再移动一次,否则我们将到达(n,m)(n,m).如果我们添加所有这些移动,我们得到公式:如果n+mn+m即使这样:2⋅(m−1)+4⋅(n−m)/2=2⋅n−22⋅(m−1)+4⋅(n−m)/2=2⋅n−2,如果n+mn+m很奇怪, 那么:2⋅(m−1)+4⋅(n−m−1)/2+1=2⋅n−32⋅(m−1)+4⋅(n−m−1)/2+1=2⋅n−3.

图解:以N=10,M=5为例

 代码实现:

#include <iostream>
using namespace std;
int T, n, m;
int main()
{
    ios_base::sync_with_stdio(false);
    cin >> T;
    while (T--) {
        cin >> n >> m;
        if (n < m) {
            swap(n, m);
        }
        if (m == 1 && n >= 3) {
            cout << -1 << "\n";
        }
        else {
            cout << 2 * n - 2 - (n + m) % 2 << "\n";
        }
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值