https://codeforces.com/contest/1668/problem/A
(时隔半年,发现昆明过后闲下来了不少于是乎菜鸡又开始写起了题解)
input
6
1 1
2 1
1 3
4 2
4 6
10 5
output
0
1
-1
6
10
17
题意
T组样例输入,询问从
(
1
,
1
)
(1,1)
(1,1) 走至
(
n
,
m
)
(n,m)
(n,m) 的最小步数,每一步中可以向 上、下、左、右,四个方向移动,但是,并不能连续两步走相同的方向
思路
看到二维地图的最短路会自然想到BFS(?,实际上看到n、m的数据范围为1e9就显然是个数学题,需要
O
(
1
)
O(1)
O(1)得出答案
既然不能连续两步走一样的方向,那试想一下斜着走(耗费两步)能不能连续走一样的方向
如下图:黑色为斜着走,而红色为实际行走的路线
发现是成立的,所以我们可以拟画一个行进路线
对于(n,m)形成的长方形,可以分割成一个正方形和一个长方形(长方形或许没有)
我们先不管绿色的长方形部分,则黑色线仍作为我们最初的行进路线
然后是看回长方形的部分
因为不能连续走一个方向,则我们还是只能斜着走
特殊的如果长方形的宽度是奇数的时候我们最后一个可以直接竖着走
同时思考一下
−
1
-1
−1的情况:
即为长或者宽为1的时候,且需要行走步数大于1,这样子无法斜着走,便没有答案
以及注意起点为(1,1),所以终点的 (n,m)需要各自减一,才是行走的距离
AC代码
#include <bits/stdc++.h>
#define endl '\n'
#define AC return 0;
using namespace std;
//#define ll long long
//#define int long long
void slove()
{
int n,m;
cin >> n >> m;
n--;
m--;
auto t = minmax(n,m);
if(t.first == 0 && t.second > 1)
{
cout << -1 << endl;
return;
}
int ans = 0;
ans += t.first * 2; //一开始走正方形所消耗的步数
int k = t.second - t.first; //取出长方形的宽
if(k & 1)
ans++,k--; //如果宽为奇数则 + 1,表示最后一步直接走向上
ans += k * 2; //计算在长方形所行走的步数
cout << ans << endl;
}
signed main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T;cin >> T; while(T--)
slove();
AC
}
没错,是写得有点啰嗦了(雾