传送门
Problem Description
In chess, each move of a knight consists of moving by two squares horizontally and one square vertically, or by one square horizontally and two squares vertically. A knight making one move from location (0,0) of an infinite chess board would end up at one of the following eight locations: (1,2), (-1,2), (1,-2), (-1,-2), (2,1), (-2,1), (2,-1), (-2,-1).
Starting from location (0,0), what is the minimum number of moves required for a knight to get to some other arbitrary location (x,y)?
Input
Each line of input contains two integers x and y, each with absolute value at most one billion. The integers designate a location (x,y) on the infinite chess board. The final line contains the word END.
Output
For each location in the input, output a line containing one integer, the minimum number of moves required for a knight to move from (0,0) to (x, y).
Sample Input
1 2
2 4
END
Sample Output
1
2
题意: 同象棋中马的行动方式,从起点出发,每次移动可以横向移动一个单位、纵向移动两个单位,或是横向移动两个单位、纵向移动一个单位,问到达一个目的地所需要花费的最短步数。
题解: 数据实在实在是太大了,不可能用dfs或bfs解决,而且图中也没有障碍,不需要用搜索的办法解决。其实就是一道思维题。下面代码中的公式,大部分人是通过打表的方式总结出来的。这个公式的解释吧,我向我的同学面对面解释也花费了一番功夫,所以很难用文字的方式再现(是我菜)。
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N = 1e9+1;
int a, b;
char str[12];
int main(){
while(~scanf("%s", str)){
if(str[0]=='E') break;
sscanf(str, "%d", &a);//读取字符串中的数值赋给a
scanf("%d", &b);
a = abs(a), b = abs(b);//把所有目的地统一集中在第一象限来处理
if(a > b) swap(a, b);//集中到b=x直线的下方处理
int ans = 0;
if(b <= 2*a){
if(a==1 && b==1) ans = 2;
else if(a==2 && b==2) ans = 4;
else ans = (a + b) / 3 + (a + b) % 3;//对不起我没办法用文字的方式解释其中的数学规律,如果有能力可以尝试用打表的方式去总结。
}else{
ans = a;
int c = (b - 2 * a) % 4;
ans += c;
ans += (b - 2 * a - c) / 2;
if(b==1&&a==0) ans = 3;
}
printf("%d\n", ans);
}
return 0;
}