📌  相关文章
📜  检查是否可以从原点到达 (X, Y),以便在每个第 i 个移动增量 x 或 y 坐标与 3^i

📅  最后修改于: 2021-10-23 08:08:35             🧑  作者: Mango

给定两个正整数XY ,任务是找出点(X, Y) 是否可以从点(0, 0)到达点 (X, Y),使得在每次第 i 次移动中,x 坐标或 y 坐标可以增加3。如果可能,则打印Yes 。否则,打印No

例子:

朴素的方法:解决给定问题的最简单的方法是通过在每个第 i 步中递减 3 i来从 (X, Y)生成所有可能的移动,并检查任何此类移动组合是否达到(0, 0) 。如果可能,则打印Yes 。否则,打印No

下面是上述方法的实现:

C++
// C++ program for the above approach
  
#include 
using namespace std;
  
// Function to find whether (0, 0) can
// be reached from (X, Y) by decrementing
// 3^i at each ith step
bool canReach(int X, int Y, int steps)
{
    // Termination Condition
    if (X == 0 && Y == 0) {
        return true;
    }
  
    if (X < 0 || Y < 0) {
        return false;
    }
  
    // Otherwise, recursively call by
    // decrementing 3^i at each step
    return (
        canReach(X - (int)pow(3, steps),
                 Y, steps + 1)
        | canReach(X, Y - (int)pow(3, steps),
                   steps + 1));
}
  
// Driver Code
int main()
{
    int X = 10, Y = 30;
    if (canReach(X, Y, 0)) {
        cout << "YES" << endl;
    }
    else
        cout << "NO" << endl;
    return 0;
}


C++
// C++ program for the above approach
  
#include 
using namespace std;
  
// Function to find whether (0, 0) can
// be reached from (X, Y) by decrementing
// 3^i at each ith step
bool canReach(int X, int Y)
{
    // Stores the number of steps
    // performed to reach (X, Y)
    int steps = 0;
    while (X || Y) {
  
        // Value of X in base 3
        int pos1 = X % 3;
  
        // Value of Y in base 3
        int pos2 = Y % 3;
  
        // Check if any has value 2
        if (pos1 == 2 || pos2 == 2) {
            return false;
        }
  
        // If both have value 1
        if (pos1 == 1 && pos2 == 1) {
            return false;
        }
  
        // If both have value 0
        if (pos1 == 0 && pos2 == 0) {
            return false;
        }
  
        X /= 3;
        Y /= 3;
        steps++;
    }
  
    // Otherwise, return true
    return true;
}
  
// Driver Code
int main()
{
    int X = 10, Y = 30;
    if (canReach(X, Y)) {
        cout << "YES";
    }
    else {
        cout << "NO";
    }
}


输出:
YES

时间复杂度: O(2 K ),其中 K 是执行的最大步骤数。
辅助空间: O(1)

高效的方法:通过将 X 和 Y 转换为基数 3,可以根据以下观察结果优化上述方法:

  • 如果基数为 3 的 X 和 Y 的值都为 1 ,则无法到达 (X, Y),因为无法在两个方向上执行此步骤。
  • 如果以 3 为底的 X 和 Y 的任何值中都有 2 ,则无法达到 (X, Y),因为这无法用 3 的完美幂表示。
  • 如果基数为 3 的 X 和 Y 的任何值都为 0 ,则无法到达 (X, Y),因为除了最后一步之外,无法执行此步骤。
  • 否则,在所有剩余的情况下 (X, Y) 都可以从 (0, 0) 到达。

根据上述观察,相应地打印结果。

下面是上述方法的实现:

C++

// C++ program for the above approach
  
#include 
using namespace std;
  
// Function to find whether (0, 0) can
// be reached from (X, Y) by decrementing
// 3^i at each ith step
bool canReach(int X, int Y)
{
    // Stores the number of steps
    // performed to reach (X, Y)
    int steps = 0;
    while (X || Y) {
  
        // Value of X in base 3
        int pos1 = X % 3;
  
        // Value of Y in base 3
        int pos2 = Y % 3;
  
        // Check if any has value 2
        if (pos1 == 2 || pos2 == 2) {
            return false;
        }
  
        // If both have value 1
        if (pos1 == 1 && pos2 == 1) {
            return false;
        }
  
        // If both have value 0
        if (pos1 == 0 && pos2 == 0) {
            return false;
        }
  
        X /= 3;
        Y /= 3;
        steps++;
    }
  
    // Otherwise, return true
    return true;
}
  
// Driver Code
int main()
{
    int X = 10, Y = 30;
    if (canReach(X, Y)) {
        cout << "YES";
    }
    else {
        cout << "NO";
    }
}
输出:
YES

时间复杂度: O(log 3 (max(X, Y))
辅助空间: O(1)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程。