三种做法 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>
using namespace std;
const int N = 1005;
int a[N][N];
int b[N][N];
void Insert(int x1, int y1, int x2, int y2, int c)
{
b[x1][y1] += c;
b[x1][y2 + 1] -= c;
b[x2 + 1][y1] -= c;
b[x2 + 1][y2 + 1] += c;
}
int main()
{
ios::sync_with_stdio(false);
int n, m, q;
int t;
cin >> n >> m >> q;
for (int i = 1;i <= n;i++)
for (int j = 1;j <= m;j++)
{
cin >> t;
Insert(i, j, i, j, t);
}
int x1, x2, y1, y2, c;
while (q--)
{
cin >> x1 >> y1 >> x2 >> y2 >> c;
Insert(x1, y1, x2, y2, c);
}
for (int i = 1;i <= n;i++)
{
for (int j = 1;j <= m;j++)
{
a[i][j] = b[i][j] - a[i - 1][j - 1] + a[i - 1][j] + a[i][j - 1];
cout << a[i][j] << ' ';
}
cout << '\n';
}
}