什么使时间限制?

时间:2018-02-20 19:56:45

标签: python recursion backtracking

N = int(input())
matrix = [[0 for x in range(N)] for y in range(N)]
def Print(matrix):
    for row in matrix:
        for elem in row:
            print(elem, end=' ')
        print()
def is_attacked(matrix,j,i,N):
    for a in range(N):
        for b in range(N):
            if matrix[a][b]:
                if j == a or i-j == b-a or b == i or i+j == b+a:
                    return(True)
    return(False)
def alg(matrix,N,number_of_queens):
    if number_of_queens == 0:
        return(True)
    for a in range(N):
        for b in range(N):
            if is_attacked(matrix,a,b,N):
                continue
            matrix[a][b] = 1
            if alg(matrix,N,number_of_queens-1):
                return(True)
            else:
                matrix[a][b] = 0
    return(False)

if alg(matrix,N,N):
    print("YES")
    Print(matrix)
else:
    print("NO")

这是对Hackerearth的八皇后国际象棋问题的解决方案,问题是我的上次输入超出时间但是我正确地实现了算法并修改了代码可能是因为python比其他语言更慢。需要花时间在我的代码中?.Hackerearth链接: https://www.hackerearth.com/practice/basic-programming/recursion/recursion-and-backtracking/tutorial/

2 个答案:

答案 0 :(得分:1)

您是否考虑过使用profiler

$ echo "8" | python3 eightqueens.py
YES
1 0 0 0 0 0 0 0 
0 0 0 0 1 0 0 0 
0 0 0 0 0 0 0 1 
0 0 0 0 0 1 0 0 
0 0 1 0 0 0 0 0 
0 0 0 0 0 0 1 0 
0 1 0 0 0 0 0 0 
0 0 0 1 0 0 0 0 
         1686133 function calls (1660190 primitive calls) in 6.467 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    6.467    6.467 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 codecs.py:318(decode)
        1    0.000    0.000    0.000    0.000 eightqueens.py:1(Print)
  25944/1    1.180    0.000    6.467    6.467 eightqueens.py:13(alg)
        1    0.000    0.000    6.467    6.467 eightqueens.py:27(blaha)
        8    0.000    0.000    0.000    0.000 eightqueens.py:29(<listcomp>)
  1660100    5.286    0.000    5.286    0.000 eightqueens.py:6(is_attacked)
        1    0.000    0.000    0.000    0.000 {built-in method _codecs.utf_8_decode}
        1    0.000    0.000    6.467    6.467 {built-in method builtins.exec}
        1    0.000    0.000    0.000    0.000 {built-in method builtins.input}
       73    0.000    0.000    0.000    0.000 {built-in method builtins.print}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

基于此,您可以看到is_attached()函数是大多数执行时间消耗最多的函数。如果您希望代码运行得更快,那么您最有可能希望集中精力。

我稍微修改了你的代码以获得你在上面看到的结果。我使用的代码如下。

def Print(matrix):
    for row in matrix:
        for elem in row:
            print(elem, end=' ')
        print()
def is_attacked(matrix,j,i,N):
    for a in range(N):
        for b in range(N):
            if matrix[a][b]:
                if j == a or i-j == b-a or b == i or i+j == b+a:
                    return(True)
    return(False)
def alg(matrix,N,number_of_queens):
    if number_of_queens == 0:
        return(True)
    for a in range(N):
        for b in range(N):
            if is_attacked(matrix,a,b,N):
                continue
            matrix[a][b] = 1
            if alg(matrix,N,number_of_queens-1):
                return(True)
            else:
                matrix[a][b] = 0
    return(False)

def blaha():
    N = int(input())
    matrix = [[0 for x in range(N)] for y in range(N)]
    if alg(matrix,N,N):
        print("YES")
        Print(matrix)
    else:
        print("NO")

import cProfile
import re
cProfile.run('blaha()')

正如您所看到的,为了运行探查器,我只是稍微改编了代码的开头。

从我所看到的你的实现我会说你在is_attacked()中有一个太粗糙的实现。你应该考虑一下,即使你只在棋盘上放了几个皇后,总是通过整个棋盘是否真的有意义。剧透:答案当然是答案。

找到提前终止的方法是优化算法的常用方法,并且分析是一个非常有用的锁孔,可以查看关于在哪里集中注意力的建议。

在我的小型计算机上,您的算法在不到四秒的时间内找到了输入“8”的解决方案,没有分析器。如果我问的话,要求是什么输入以及时间限制是什么?

答案 1 :(得分:0)

Python因为执行速度慢而臭名昭着 - 当你只是拥有纯粹的python而没有调用任何用C&#39; C&#39; - 尤其是当你的Big O复杂度很高时。 (这必须至少为O(n*n)

但是,如果您保存中间查找,则会略有优化:

在这两个功能中,您可以:

for a in range(N):
    mat = matrix[a]
    for b in range(N):
        ...
        mat[b]

稍后重复mat