1. 程式人生 > 實用技巧 >b_lg_塗色(從小區間做起,討論s[l]和s[r]的關係)

b_lg_塗色(從小區間做起,討論s[l]和s[r]的關係)

每次你可以把一段連續的木版塗成一個給定的顏色,後塗的顏色覆蓋先塗的顏色。例如第一次把木版塗成 RRRRR,第二次塗成 RGGGR,第三次塗成 RGBGR,達到目標。用盡量少的塗色次數達到目標。
提示:n<50

方法一:dp

題目等價於將目標串變為空串的最小消除次數,比如 xxAAAxx,AAA 可以一次消掉

  • 思考狀態轉移方程
    • f[i][j]=min(f[i+1][j], f[i][j-1]),if (s[i]=s[j]),當他們相等時,塗色的時候可以在塗 s[i,j-1]/s[i+1,j] 時順便多塗一格
    • f[i][j]=min(f[i+1][j], f[i][k]+f[k+1][j]),if (s[i]≠s[j])
#include<bits/stdc++.h>
using namespace std;
int main() {
    std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    string s; cin>>s;
    int n=s.size(), f[n+1][n+1]; memset(f, 0x3f3f3f3f, sizeof f);
    for (int i=1; i<=n; i++) f[i][i]=1;

    for (int len=2; len<=n; len++)
    for (int l=1; l<=n-len+1; l++) {
        int r=l+len-1;
        if (s[l-1]==s[r-1]) f[l][r]=min(f[l+1][r], f[l][r-1]);
        else for (int k=l; k<r; k++) f[l][r]=min(f[l][r], f[l][k]+f[k+1][r]);
    }
    cout<<f[1][n];
    return 0;
}

複雜度分析

  • Time\(O(n^3)\)
  • Space\(O(n^2)\)