c++ - 查找在螺旋矩阵中行进的 N 个正方形的坐标
问题描述
我解决了一个在线判断问题(输入正确),但是我的算法太慢了。
我有一个可变大小的矩阵,并想找到行进n
的正方形数量的坐标。在这个例子中,矩阵的大小是:。表示行数和列数。8
从点开始x, y
: (1, 1) 和;
- 尽可能向右走
- 尽可能往下走
- 尽可能向左走
- 尽可能往上走
鉴于i = 53
通过到达计算坐标,从每个经过的方格开始n = 0
并累加。1
n
n == i
我试过的:
(免责声明:我只是发布这个,所以你可以看到我是多么天真)
在我最初的编程问题中,我通过创建一个m
具有矩阵大小的变量来实现它,所以在这种情况下,并在每次和移动m = 8
之后推导出它。right
left
y = 0 //y will move first, starts offboard at imaginary column `0`
x = 1 //start from row 1
m = 8
right: { y+= i; m -= 1;} //x = 1, y = 8 / m = 7
down: { x+= m; }//x = 8, y = 8
left: { y-= m; m -= 1; } //x = 8, y = 1 / m = 6
up: { x-=m; } // x = 2, y = 1
并且迭代,直到另一个创建的变量sumofsteps
,以总结在这种情况下m
到达的正方形数量。i
53
这当然是非常幼稚的,因为在某些情况下,矩阵可能1073741824
与步骤数一样大1152921504603393520
,而在我的程序中,这需要很长时间才能解决。
单个输入的程序运行时间限制为 1.0 秒。
有没有更快的方法来找到坐标?
#include <iostream>
#include <sstream>
void GetSpiralFinalCoordinates(
const unsigned long long gridSize,
const unsigned long long finalDestSteps,
unsigned long long& x, unsigned long long& y)
{
x = 1;
y = 0;
unsigned long long stepsWalked{0};
unsigned long long currentStepsToWalk = gridSize;
enum movedir {RIGHT = 0, DOWN, LEFT, UP};
while(stepsWalked < finalDestSteps)
{
for(int i=0; i<4; i++)
{
if(stepsWalked + currentStepsToWalk < finalDestSteps)
{
stepsWalked += currentStepsToWalk;
switch(i)
{
case RIGHT: { y+= currentStepsToWalk; currentStepsToWalk -= 1;}break;
case DOWN: { x+= currentStepsToWalk; }break;
case LEFT: { y-= currentStepsToWalk; currentStepsToWalk -= 1; }break;
case UP: { x-=currentStepsToWalk; }break;
}
} else {
int lastAmountOfStepsToWalk = finalDestSteps - stepsWalked;
switch(i)
{
case RIGHT: { y+= lastAmountOfStepsToWalk; }break;
case DOWN: { x+= lastAmountOfStepsToWalk; }break;
case LEFT: { y-= lastAmountOfStepsToWalk; }break;
case UP: { x-=lastAmountOfStepsToWalk; }break;
}
stepsWalked = finalDestSteps + 1;
break;
}
}
}
}
int main()
{
unsigned long long x, y;
unsigned long long a, b;
std::string line;
std::getline(std::cin, line);
std::istringstream issline(line);
issline >> a;
issline >> b;
GetSpiralFinalCoordinates(a,b, x, y);
std::cout << x << " " << y << std::endl;
}
解决方案
是的,有一个模式。您可以从这个开始(您可能会遇到较大值的堆栈溢出问题,但如果您愿意,很容易替换递归)
void GetSpiralFinalCoordinates(
const unsigned long long s,
const unsigned long long n,
unsigned long long& x,
unsigned long long& y) {
// calculate max n for external ring
const unsigned long long maxN = s * 4 - 4;
// if not in the external ring we will use recursion
if (n > maxN) {
unsigned long long subX;
unsigned long long subY;
GetSpiralFinalCoordinates(s - 2, n - maxN, subX, subY);
x = subX + 1;
y = subY + 1;
return;
}
if (n <= s) {
x = n;
y = 1;
return;
}
if (n <= 2 * s - 1) {
x = s;
y = n - s + 1;
return;
}
if (n <= 3 * s - 2) {
x = s - n + (2 * s - 1);
y = s;
return;
}
x = 1;
y = 4 * s - n - 2;
}
推荐阅读
- html - 使用 Bootstrap flex 垂直和水平对齐
- ios - 如何在 iOS 中格式化一个空的(NDEFFormatable)NFC 标签
- ajax - Word Press 自定义表单链接
- python - 如何在 Python 中从文本文件中读取数据?
- zurb-foundation - get.foundation/sites/docs/v/5.5.3/ 上的基础 5 文档不再可用
- r - ggplot2:CairoSVG 更改点大小
- python - 使用 scipy 的 cdist 函数时无法计算马氏距离
- php - html2pdf PHP 生成一个额外的空白页
- blockchain - 在引导 Corda 网络时出现“错误:无效或损坏的 jarfile corda.jar”
- laravel - 我想使用 laravel 向相关类别展示产品