dp专题

Posted wory

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了dp专题相关的知识,希望对你有一定的参考价值。

1. Leetcode 943

解法一:

技术图片
 1 class Solution:
 2     def shortestSuperstring(self, A):
 3         self.min_path = []
 4         self.min_length = float("inf")
 5         self.get_dis_mat(A)
 6         for i in range(len(A)):
 7             self.dfs(len(A), i, [i], 0)
 8 
 9         res = A[self.min_path[0]]
10         for i in range(1, len(A)):
11             cut = 30 - self.dis_mat[self.min_path[i - 1]][self.min_path[i]]
12             res += A[self.min_path[i]][cut:]
13         return res
14 
15     def get_dis_mat(self, A):
16         n = len(A)
17         self.dis_mat = [[0] * n for _ in range(n)]
18         for i in range(n):
19             for j in range(n):
20                 self.dis_mat[i][j] = self.cal_dis(A[i], A[j])
21         print(self.dis_mat)
22 
23     def dfs(self, total, cur, path, min_len):
24         if min_len >= self.min_length:
25             return
26         if len(path) == total and min_len < self.min_length:
27             self.min_path = copy.copy(path)
28             self.min_length = min_len
29         for nex in range(total):
30             if nex not in path:
31                 path.append(nex)
32                 self.dfs(total, nex, path, min_len + self.dis_mat[cur][nex])
33                 path.pop()
34 
35     def cal_dis(self, str1, str2):
36         # 用30 - i将最大路径问题转换成最小路径,方便截枝
37         for i in range(min(len(str1), len(str2)), -1, -1):
38             if str2[:i] == str1[-i:]:
39                 return 30 - i
40         return 30
View Code

解法二:

技术图片
 1 class Solution:
 2     def shortestSuperstring(self, A):
 3         dis_mat = self.get_dis_mat(A)
 4         n = len(A)
 5         dis_dp, path_dp = self.dp(A, n, dis_mat)
 6         cur = min(range(n), key=lambda x: dis_dp[-1][x])
 7         s, path = (1 << n) - 1, [cur]
 8         while path_dp[s][cur] != -1:
 9             prev = path_dp[s][cur]
10             path.append(prev)
11             s -= (1 << cur)
12             cur = prev
13         path.reverse()
14         res = A[path[0]]
15         for i in range(1, n):
16             cut = dis_mat[path[i - 1]][path[i]]
17             res += A[path[i]][cut:]
18         return res
19 
20     def cal_dis(self, str1, str2):
21         for i in range(min(len(str1), len(str2)), -1, -1):
22             if str2[:i] == str1[-i:]:
23                 return i
24         return 0
25 
26     def get_dis_mat(self, A):
27         n = len(A)
28         dis_mat = [[float("inf")] * n for _ in range(n)]
29         for i in range(n):
30             for j in range(n):
31                 dis_mat[i][j] = self.cal_dis(A[i], A[j])
32         return dis_mat
33 
34     def dp(self, A, n, dis_mat):
35         dis_dp = [[float("inf")] * n for _ in range(1 << n)]
36         path_dp = [[-1] * n for _ in range(1 << n)]
37         for i in range(n):
38             dis_dp[1 << i][i] = len(A[i])
39         for s in range(1 << n):
40             for i in range(n):
41                 if s & (1 << i) == 0:
42                     continue
43                 for j in range(n):
44                     if dis_dp[s - (1 << i)][j] + len(A[i]) - dis_mat[j][i] < dis_dp[s][i]:
45                         dis_dp[s][i] = dis_dp[s - (1 << i)][j] + len(A[i]) - dis_mat[j][i]
46                         path_dp[s][i] = j
47         return dis_dp, path_dp
View Code

 

以上是关于dp专题的主要内容,如果未能解决你的问题,请参考以下文章

Kuangbin专题12 基础DP

UVA-624 dp专题A

UESTC 电子科大专题训练 DP-E

数位dp专题

区间dp专题练习

LeetCode dp专题