三种做法 1.模拟每次走一个点 O(10的18次方)
2.模拟每次走一条边 O(10的9次方)
3.找数学规律 O(1)
1.模拟方法
#include <iostream>
#include <algorithm>
using namespace std;
int X, Y;
int main()
{
cin >> X >> Y;
int x = 0, y = 0;
int len = 0;
int i = 1, b = 1;
while (check(x, y))
{
if (i == 1) //左走b次
{
for (int j = 0;j < b && check(x, y);j++)
x = x - 1, len++;
if (!check(x, y))
break;
}
if (i == 2) //上走b次
{
for (int j = 0;j < b && check(x, y);j++)
y = y + 1, len++;
b++; //步数+1
if (!check(x, y))
break;
}
if (i == 3) //右走b次
{
for (int j = 0;j < b && check(x, y);j++)
x = x + 1, len++;
if (!check(x, y))
break;
}
if (i == 4) //下走b次
{
for (int j = 0;j < b && check(x, y);j++)
y = y - 1, len++;
b++;
if (!check(x, y))
break;
}
i = i % 4 + 1;
}
cout << len;
}
2.找规律做法
我们发现如果每个以一个正方形向外扩展,正方形边长(2,4,6...)那么他的
右上顶点距离是(2n)*(2n) x==y,x>0,y>0
左上顶点距离是(2n-1)*(2n) x==-y,x<0,y>0
右下顶点距离是(2n)*(2n+1) x==-y,x>0,y<0
左下顶点距离是(2n-1)*(2n-1) x==y,x<0,y<0
如果是在上直线 |x|<=y(左走到右)
在下直线 |x|<=|y|+1(从右走到左)
在左直线 |y|<=|x| (从下走到上)
在右直线 |y|<=x (从上走到下)
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
/*
找数学规律问题\线性规划
*/
typedef long long ll;
int main()
{
ll x, y;
cin >> x >> y;
ll res = 0;
if (fabs(x) <= y)
{
int n = x;
res = (2 * y - 1) * (2 * y) + y + x;
}
else if (fabs(y) <= x)
{
res = (2 * x) * (2 * x) + x - y;
}
else if (fabs(x) <= fabs(y) + 1&&y<0) //确保是在下面那条边
{
ll n = fabs(y); //y不变,但是y的值为负数,计算可能出错,于是取绝对值
res = (2 * n) * (2 * n + 1) + n - x;
}
else if (fabs(y) <= fabs(x))
{//特殊
ll n = fabs(x); //x不变,但是x的值是负数
res = (2 * n - 1) * (2 * n - 1) + y - (-n + 1);
//这里加一是因为点在左边那条边的话,边的长度是2*n-1,x轴下面占n-1,上面占n
}
cout << (ll)res;
}