📌  相关文章
📜  数字的排列,使得两个连续数字的和是一个完美的平方

📅  最后修改于: 2022-05-13 01:57:54.531000             🧑  作者: Mango

数字的排列,使得两个连续数字的和是一个完美的平方

先决条件:哈密顿循环

给定一个整数 n(>=2),找到一个从 1 到 n 的数字排列,使得该排列的两个连续数字之和是一个完全平方。如果这种排列不可能打印“No Solution”。

例子:

Input : 17
Output : [16, 9, 7, 2, 14, 11, 5, 4, 12, 13, 3, 6, 10, 15, 1, 8, 17]
Explanation : 16+9 = 25 = 5*5, 9+7 = 16 = 4*4, 7+2 = 9 = 3*3 and so on.

Input: 20
Output: No Solution

Input : 25
Output : [2, 23, 13, 12, 24, 25, 11, 14, 22, 3, 1, 8,  
          17, 19, 6, 10, 15, 21, 4, 5, 20, 16, 9, 7, 18]

方法:
我们可以表示一个图,其中从 1 到 n 的数字是图的节点,如果 (i+j) 是一个完美的正方形,则在第 i 个和第 j 个节点之间有一条边。然后我们可以搜索图中是否有任何哈密顿路径。如果至少有一条路径,那么我们打印一条路径,否则我们打印“No Solution”。

平方和

方法:

1. First list up all the perfect square numbers 
   which we can get by adding two numbers.
   We can get at max (2*n-1). so we will take 
   only the squares up to (2*n-1).
2. Take an adjacency matrix to represent the graph.
3. For each number from 1 to n find out numbers with 
   which it can add upto a perfect square number.
   Fill respective cells of the adjacency matrix by 1.
4. Now find if there is any Hamiltonian path in the 
   graph using backtracking as discussed earlier.  
Python3
# Python3 program for Sum-square series using
# hamiltonian path concept and backtracking
  
# Function to check wheter we can add number
# v with the path in the position pos.
def issafe(v, graph, path, pos):
      
    # if there is no edge between v and the
    # last element of the path formed so far
    # return false.
    if (graph[path[pos - 1]][v] == 0):
        return False
      
    # Otherwise if there is an edge between 
    # v and last element of the path formed so
    # far, then check all the elements of the
    # path. If v is already in the path return
    # false.
    for i in range(pos):
          
        if (path[i] == v):
            return False
  
    # If none of the previous cases satisfies
    # then we can add v to the path in the
    # position pos. Hence return true.
    return True
  
# Function to form a path based on the graph.
def formpath(graph, path, pos):
  
    # If all the elements are included in the
    # path i.e. length of the path is n then
    # return true i.e. path formed.
    n = len(graph) - 1
    if (pos == n + 1):
        return True
  
    # This loop checks for each element if it
    # can be fitted as the next element of the
    # path and recursively finds the next 
    # element of the path.
    for v in range(1, n + 1):
          
        if issafe(v, graph, path, pos):
            path[pos] = v
              
            # Recurs for next element of the path.
            if (formpath(graph, path, pos + 1) == True):
                return True
              
            # If adding v does not give a solution
            # then remove it from path
            path[pos] = -1
              
    # if any vertex cannot be added with the 
    # formed path then return false and 
    # backtracks.
    return False
  
# Function to find out sum-square series.
def hampath(n):
      
    # base case: if n = 1 there is no solution
    if n == 1:
        return 'No Solution'
  
    # Make an array of perfect squares from 1 
    # to (2 * n-1)
    l = list()
      
    for i in range(1, int((2 * n-1) ** 0.5) + 1):
        l.append(i**2)
  
    # Form the graph where sum of two adjacent
    # vertices is a perfect square
    graph = [[0 for i in range(n + 1)] for j in range(n + 1)]
      
    for i in range(1, n + 1):
        for ele in l:
              
            if ((ele-i) > 0 and (ele-i) <= n
                and (2 * i != ele)):
                graph[i][ele - i] = 1
                graph[ele - i][i] = 1
  
    # strating from 1 upto n check for each 
    # element i if any path can be formed 
    # after taking i as the first element.
    for j in range(1, n + 1):
        path = [-1 for k in range(n + 1)]
        path[1] = j
  
        # If starting from j we can form any path
        # then we will return the path
        if formpath(graph, path, 2) == True:
            return path[1:]
              
    # If no path can be formed at all return
    # no solution.
    return 'No Solution'
      
# Driver Function
print(17, '->', hampath(17))
print(20, '->', hampath(20))
print(25, '->', hampath(25))


输出:

17 -> [16, 9, 7, 2, 14, 11, 5, 4, 12, 13, 3, 6, 10, 15, 1, 8, 17]
20 -> No Solution
25 -> [2, 23, 13, 12, 24, 25, 11, 14, 22, 3, 1, 8, 17, 19, 6, 10, 
       15, 21, 4, 5, 20, 16, 9, 7, 18]

讨论:
这种回溯算法需要指数时间来找到哈密顿路径。因此,该算法的时间复杂度是指数级的。
在 hampath(n)函数的最后一部分,如果我们只打印路径而不是返回它,那么它将打印所有可能的哈密顿路径,即所有可能的表示。
实际上,对于 n = 15,我们首先会得到这样的表示。对于 n<15,没有表示。对于 n = 18、19、20、21、22、24,也没有哈密顿路径。对于其余的数字,它运作良好。

参考:Numberphile