[GO] Points à noter lors de la résolution de problèmes DP avec Python

Aperçu

Lorsque je résolvais le problème DP (programmation dynamique) d'AtCoder, j'ai rencontré un phénomène selon lequel le code qui serait AC dans d'autres langages serait TLE s'il s'agissait de Python / PyPy, je le laisserai donc comme un mémorandum.

À propos du problème DP

Comme expliqué en détail dans cet article, il existe plusieurs façons de résoudre le problème DP, mais si vous le divisez grossièrement, activez l'instruction for de bas en haut. Il existe deux méthodes, l'une consiste à créer une table DP et l'autre est la récurrence mémorielle qui appelle des fonctions récursives de haut en bas. Dans tous les cas, il en est de même en ce sens qu'il accélère le traitement en conservant le résultat calculé, mais dans le cas de récurrence mémorielle, il y a un surcoût d'appel de fonction, donc c'est dans le délai dans certaines langues. Il y a des moments où le processus ne se termine pas et devient TLE.

exemple

Problème du concours récapitulatif DP B: Frog2

Solution 1: DP de bas en haut par instruction for

N, K = map(int, input().split())
h = list(map(int, input().split()))
dp = [10**9] * N

for i in range(N):
    if i == 0:
        dp[0] = 0
    elif i == 1:
        dp[1] = abs(h[0]-h[1])
    else:
        for j in range(1, K+1):
            if j > i:
                break
            dp[i] = min(dp[i], dp[i - j] + abs(h[i - j] - h[i]))

print(dp[N-1])

résultat

Langue résultat
Python TLE
PyPy AC
Go AC

Soumettre en Python sera TLE et Soumettre en PyPy sera AC ). Vous pouvez également obtenir AC en écrivant un code similaire dans un langage rapide tel que Go.

Solution 2: récurrence de la mémorisation (nombre d'appels de fonction: grand)

Lorsqu'il est écrit en Python


import sys
sys.setrecursionlimit(10**6)

N, K = map(int, input().split())
h = list(map(int, input().split()))
INF = 10**9
dp = [INF] * N

def solve(n):
    if dp[n] != INF:
        return dp[n]

    if n == 0:
        dp[n] = 0
    elif n == 1:
        dp[n] = abs(h[0] - h[1])
    else:
        for i in range(1, K + 1):
            if n - i < 0:
                break
            cost = solve(n - i) + abs(h[n - i] - h[n])
            dp[n] = min(dp[n], cost)

    return dp[n]

print(solve(N-1))

Lorsqu'il est écrit en Go


package main

import (
	"fmt"
	"math"
)

var (
	N, K, INF int
	h, dp []int
)

func solve(n int) int {
	if dp[n] != INF {
		return dp[n]
	}

	if n == 0 {
		dp[n] = 0
	} else if n == 1 {
		dp[n] = int(math.Abs(float64(h[n] - h[n-1])))
	} else {
		for i := 1; i <= K; i++ {
			if n - i < 0 {
				break
			}
			var cost =  solve(n - i) + int(math.Abs(float64(h[n-i]-h[n])))
			dp[n] = int(math.Min(float64(dp[n]), float64(cost)))
		}
	}

	return dp[n]
}

func main() {
	fmt.Scan(&N, &K)
	h = make([]int, N)
	dp = make([]int, N)
	INF = int(math.Pow(10, 9))

	for i := 0; i < N; i++ {
		fmt.Scan(&h[i])
	}
	for i := 0; i < N; i++ {
		dp[i] = INF
	}

	fmt.Println(solve(N - 1))
}

résultat

Langue résultat
Python TLE
PyPy TLE
Go AC

Il s'agit d'une conversion récursive dite de mémo ordinaire, mais elle devient TLE lorsqu'elle est soumise avec Python ou PyPy, et [Écrire et soumettre dans un langage à grande vitesse tel que Go] Ensuite, il devient AC](https://atcoder.jp/contests/dp/submissions/14452835). Afin de prendre AC avec Python / PyPy, un autre appareil est nécessaire.

Solution 3: récurrence de la mémorisation (nombre d'appels de fonction: petit)

import sys
sys.setrecursionlimit(10**6)

N, K = map(int, input().split())
h = list(map(int, input().split()))
INF = 10**9
dp = [INF] * N

def solve(n):
    if dp[n] != INF:
        return dp[n]

    if n == 0:
        dp[n] = 0
    elif n == 1:
        dp[n] = abs(h[0] - h[1])
    else:
        for i in range(1, K+1):
            if n - i < 0:
                break
            if dp[n - i] != INF:
                #Dp pour réduire le nombre d'appels de fonction[n-i]Utilisez-le s'il est déjà calculé
                cost = dp[n - i] + abs(h[n - i] - h[n])
            else:
                cost = solve(n - i) + abs(h[n - i] - h[n])
            dp[n] = min(dp[n], cost)

    return dp[n]

print(solve(N-1))

résultat

Langue résultat
Python TLE
PyPy AC
Go AC

C'est presque le même code que la solution 2, mais dans ce cas, il vérifie si dp [n-i] a été calculé avant d'appeler résoudre (n-i), et s'il est calculé, il est utilisé. En faisant cela, vous pouvez réduire la surcharge de l'appel de fonction et le rendre AC avec PyPy. Cependant, même avec cette ingéniosité, ce sera TLE une fois soumis en Python.

Résumé

Les résultats pour chaque solution et langue sont les suivants. En d'autres termes, si vous le soumettez en Python, vous pouvez prendre AC sans être particulièrement conscient des langages à haute vitesse tels que AC et Go si vous concevez TLE et PyPy.

Screen Shot 2020-06-18 at 22.01.10.png

Par conséquent, il peut être judicieux de soumettre le problème DP dans un langage à grande vitesse tel que C ++ ou Go. Si vous voulez vraiment le résoudre avec Python, vous devez être conscient de ce qui suit.

Si vous avez d'autres erreurs telles que des points que vous avez remarqués ou une reconnaissance, il serait utile que vous puissiez les signaler.

Recommended Posts

Points à noter lors de la résolution de problèmes DP avec Python
Précautions lors de l'utilisation de six avec Python 2.5
Précautions lors du traitement des structures de contrôle dans Python 2.6
[Développement Web avec Python] Précautions lors de l'enregistrement des cookies
Résoudre les mathématiques avec Python (incomplet)
Précautions lors du traitement du type ROS MultiArray en Python
Problèmes lors de la création d'un outil de conversion csv-json avec python
Résolution de Nampre avec Python (partie 2)
Erreur lors de la lecture avec python
Comment écrire hors ligne en temps réel Résolution des problèmes E05 avec Python
Précautions lors de l'utilisation de Pit avec Python
Résolvez le problème des 4 couleurs grâce à l'optimisation des combinaisons
Précautions lors de l'installation de tensorflow avec anaconda
Recommandation de résolution des problèmes d'AtCoder avec python (20200517-0523)
Précautions lors de la création d'un générateur Python
Précautions lors de l'utilisation de phantomjs de python
Quand matplotlib ne fonctionne pas avec python2.7
Lors de l'utilisation de MeCab avec python dans virtualenv
[Python] Formater quand to_csv avec des pandas
Extrait de code pour une recherche de bits complète avec python
Précautions lors du décapage d'une fonction en python
Remarques lors de la création d'un environnement avec python
Résolution des problèmes de planification des infirmières grâce à l'optimisation des combinaisons
Erreur lors de l'installation d'un module avec Python pip
FizzBuzz en Python3
Grattage avec Python
Environnement et utilisation recommandés lors du développement avec Python
Statistiques avec python
Introduction à l'optimisation mathématique Python Résoudre des problèmes de mathématiques au collège avec pulp
Grattage avec Python
Résolution des problèmes d'organisation des districts scolaires grâce à l'optimisation des combinaisons
Python avec Go
[Python] DP ABC184D
Conseils personnels lorsque vous faites diverses choses avec Python 3
Twilio avec Python
Intégrer avec Python
Jouez avec 2016-Python
AES256 avec python
Testé avec Python
[Python] Précautions lors de l'affectation de valeurs à des tableaux multidimensionnels
python commence par ()
Enquête lorsque l'importation ne peut pas être effectuée avec python
Un mémo lors de la création d'un environnement python avec miniconda
Encodage de caractères lors du traitement de fichiers en Python 3
Précautions lors de l'utilisation de la bibliothèque google-cloud avec GAE / py
avec syntaxe (Python)
[python] [vscode] Lorsque vous vous fâchez avec space-tab-mixed
Résolution du modèle Lorenz 96 avec Julia et Python
Bingo avec python
Zundokokiyoshi avec python
Matériel à lire lors de la mise en route de Python
Résolvez le problème du sac à dos Python avec l'algorithme glouton
Excel avec Python
Micro-ordinateur avec Python
Qu'utilisez-vous lorsque vous testez avec Python?
[Python] Personnalisez la palette de couleurs lors du dessin de graphiques avec matplotlib
Cast avec python
BigQuery-Python s'est avéré utile lors de l'utilisation de BigQuery à partir de Python
Le problème que Windows python est appelé dans pipenv sur WSL
Précautions lors de l'utilisation de sqlite3 de macOS Sierra (10.12) avec le multitraitement
"CheckiO" où vous pouvez étudier Python tout en résolvant des problèmes