zoukankan      html  css  js  c++  java
  • P4170 [CQOI2007]涂色

    戳这里

    • 先看一下题意:

      ​ 给你一个 n 长度的木板,刚开始是没有颜色的,现在你需要用最少的涂色次数,让这个木板的颜色变成给定的目标颜色

    • 解析

      1. 读懂题意,发现这是一个求处理一个区间的最小操作数的题目,这时候就要考虑能不能用区间DP处理这个题目,一般来说,区间DP的时间复杂度为 \(n^3\)\(n^2\),本题 n 最大仅 50 ,在时间复杂度上满足要求。

      2. 在确定题目是区间DP后,我们要思考这个题的 状态转移方程

        • 定义\(f[i][j]\) 为 处理好区间 i 至 j 涂色的最小次数

        • 先考虑区间长度为 1 的情况,如果木板的长度只有 1,那么涂色次数很显然就是 1。

        • 在考虑一下区间长度为 2 时

          首先,如果两端的颜色一样,那么我们只需要一次涂色,就能把这个区间染成需要的颜色

          如果,两端的颜色不一样,那么染色的次数就应该时 2 了

        • 当区间长度更大时,会怎么样呢

          假设我们当前要计算的区间为 \(f[i][j]\)

          如果,\(s[i] == s[j]\) ,那么,我们可以第一笔就涂满整个区间,所以,此时的状态可以由 \(f[i+1][j]\)\(f[i][j-1]\) 中较小的转移,即

          \[f[i][j] = min(f[i+1][j],f[i][j-1]) \]

          那如果,\(s[i] != s[j]\),我们就只能枚举断点来找到最优的方案,即

          \[f[i][j] = min(f[i][j],f[i][k]+f[k+1][j]) \]

      3. 以上就是本题的解释。在写区间DP的时候,感觉难的主要就是区间和合并问题,还有就是一些特殊的优化 (四边形不等式)

    • 放代码QwQ

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int Inf = 0x7f7f7f7f;
    
    int dp[233][233];
    char s[233];
    
    int main(){
        scanf("%s",s+1);
        int Len = strlen(s+1);
        for(int i=1;i<=Len;i++)
            dp[i][i] = 1;
        for(int len = 2;len <= Len;len++)
        {
            for(int l=1;l+len-1<=Len;l++)
            {
                int r = l + len - 1;
                dp[l][r] = Inf;
                if( s[l] == s[r] )  dp[l][r] = min(dp[l+1][r],dp[l][r-1]);
                else 
                    for(int k=l;k<r;k++)
                        dp[l][r] = min(dp[l][r],dp[l][k] + dp[k+1][r]);
            }
        }
        printf("%d",dp[1][Len]);
        return 0;
    }
    
  • 相关阅读:
    WPF xaml中列表依赖属性的定义
    查询英语单词
    WPF 界面如何绑定Command
    C# 获取当前屏幕的宽高和位置
    WPF 列表开启虚拟化的方式
    WPF MVVM UI分离之《交互与数据分离》
    WPF TextBlock IsTextTrimmed 判断文本是否超出
    局部变量表中Slot复用对垃圾回收的影响详解
    ArrayList中的Iterator详解
    oracle
  • 原文地址:https://www.cnblogs.com/HexQwQ/p/12050080.html
Copyright © 2011-2022 走看看