这段代码的逻辑和方法是什么?

时间:2019-06-23 13:50:02

标签: c++ algorithm

您必须访问的所有单元格都是n * m网格,您只能访问每个单元格一次,而您必须访问它们的方式是,当从一个单元格移动到另一个单元格时,向量(从数学上来说) (即ordered_pa​​ir(dx,dy))不再用于其他任何移动。 也可能有其他解决方案,但是我对为什么这种解决方案特别感兴趣。这个问题来自codeforces https://codeforces.com/contest/1180/problem/D

#include<bits/stdc++.h>
using namespace std;
int main() {
    int n,m;
    cin>>n>>m;
    int st=0,end=n*m-1;
    for(int i=0;i<n*m;i++) {
        if(i%2==0) {
             cout<<st/m+1<<' '<<st%m+1<<endl;
             st++;
        }
        else {
            cout<<end/m+1<<' '<<end%m+1<<endl;
            end--;
        }
    }
}

2 个答案:

答案 0 :(得分:2)

算法以网格的某些顺序在第一个和最后一个尚未输入的单元格之间循环。我们需要2件作品来说明其工作原理:

首先,我们注意到,对于订购这种网格(行或列主数据)的典型方法,任何矢量都通过其排序步长来唯一标识(有效部分的主要部分和次要部分实际上是除数)和各边长度的其余部分,并且这两个部分彼此独立。)

第二,我们使排序的步长单调减少,因为我们减少了它可以移动到每一步的可能的排序值量,因为我们删除了它可能到达的最远点。 / p>

当我们将其组合在一起时,我们会发现所有移动都必须不同,因为每个移动的顺序长度都不同,并且不同长度的步长具有唯一的矢量移动。

请注意,由于在移动上还存在一个符号,并且它也构成了一个不同的向量,并且我们已经采用了所有排序长度,因此我们已经用完了所有可能的移动向量的一半(另一半是反向运动),由此我们可以证明所有满足问题的运动集也必须具有此属性。

答案 1 :(得分:0)

考虑它是否是一维数组。等效的一维算法将从第一个单元格开始,向前跳到最后一个单元格,向后跳到第二个单元格,再向前到倒数第二个单元格,向后跳到第三个单元格,依此类推,直到跳转将其带到中间。由于每个向前的跳跃都小于最后一个,并且向后的跳跃也是如此,因此每个跳跃的位移都不同。

2D版本只是该版本的嵌套版本。首先,它访问第一行和最后一行(由X坐标定义);然后访问第二行和倒数第二行;等等。在每一行中,它使用一维算法。