664. Strange Printer
阿新 • • 發佈:2019-01-08
There is a strange printer with the following two special requirements:
- The printer can only print a sequence of the same character each time.
- At each turn, the printer can print new characters starting from and ending at any places, and will cover the original existing characters.
Given a string consists of lower English letters only, your job is to count the minimum number of turns the printer needed in order to print it.
Example 1:
Input: "aaabbb" Output: 2 Explanation: Print "aaa" first and then print "bbb".
Example 2:
Input: "aba" Output: 2 Explanation: Print "aaa" first and then print "b" from the second place of the string, which will cover the existing character 'a'.
Hint: Length of the given string will not exceed 100.
思路: dp[i][j]的意義沒啥好說的,裡面還要套一層迴圈也好說,但是這層迴圈的意義何在呢?
假設三層迴圈變數是i,j,k,因為i..k之間可能會與後面的k+1..j發生關聯,即最佳的dp[i][j]在處理i..k中某一個的時候正好把k+1..j中的某個數給處理掉了,但是我們不知道最佳的dp[i][j]在i..k哪個位置與k+1..j的哪個位置聯絡在了一起。
那我們就用k表示處理到第k個位置的時候,正好把j位置的也一併處理掉了
(1)為什麼是最右邊的j位置:因為如果是中間位置,k總會遍歷到的
(2)最右邊要留出來,因為計算距離為d時,只能用距離為0..d-1的dp陣列
class Solution { public int strangePrinter(String s) { int n = s.length(); if(n == 0) return 0; int[][] dp = new int[n][n]; for(int i=0; i<n; i++) dp[i][i] = 1; char[] cs = s.toCharArray(); for(int d=1; d<n; d++) { for(int i=0; i+d<n; i++) { dp[i][i+d] = d+1; for(int j=i+1; j<=i+d; j++) { int t = dp[i][j-1] + dp[j][i+d]; if(cs[j-1] == cs[i+d]) t--; dp[i][i+d] = Math.min(dp[i][i+d], t); } } } return dp[0][n-1]; }
或者換個思路:
1. 如果把某個位置k的刷好了,那肯定就不要再改動這個k位置了,因為改動需要1次粉刷,可定就不是最優的了
2. 既然不能動以及刷好了的,那我們就可以吧原問題divide成2個互相獨立的問題
3. 而且在刷k的時候,可能也可以把後面的順帶處理掉,至於為什麼是最後這個數,參考上面的分析
class Solution:
def strangePrinter(self, s):
"""
:type s: str
:rtype: int
"""
s = ''.join(a for a,b in zip(s, '#'+s) if a!=b)
n = len(s)
if n==0: return 0
dp = [[999999 for _ in range(n)] for _ in range(n)]
for i in range(n): dp[i][i]=1
for dist in range(1, n):
for left in range(0, n-dist):
right = left + dist
for k in range(left, right):
cur = dp[left][k]+dp[k+1][right]
if s[k]==s[right]: cur -= 1
dp[left][right] = min(dp[left][right], cur)
return dp[0][n-1]
s=Solution()
print(s.strangePrinter('aaabbb'))
print(s.strangePrinter('aba'))
至於DP子問題嚴格的證明,在討論去也沒發現。。。。