涂色——区间dp
P4170 [CQOI2007]涂色 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
一道很好的题。一定要明确dp问题就是分析状态的,不要太细节,不要管每个区间内具体有什么颜色。这道题看了大佬的题解后,真的有了很大的感触。
大佬做法:
1.先判断出来这是区间dp,然后画数轴。
2.因为区间dp的核心思想是由一个个小区间进行合并成为了大区间,所以我们应该先模拟长度最小的区间,也就是长度为1的区间。
3.在研究长度为n的区间的时候,可以在数轴上标明覆盖区间,更直观。
4.以这道题为例
1.长度为1的区间的值即涂色次数就是1
2.长度为2的区间的值,是由两个长度为1的区间进行合并
1.如果两个区间的颜色相同,涂色次数=其中一个长度为1的区间
2.如果两个区间颜色不相同,涂色次数=两个长度为1的区间涂色次数之和
3.长度为3的区间的值,由一个长度为2的区间+一个长度为1的区间合并
1.这时候就要思考状态转移方程式了
2.利用数轴,标明各种情况,思考不同情况下需要写出来的状态转移方程式
3.设此时研究的区间左右端点为i与i+2 (一般化)
观察整个区间,拿支荧光笔画一下,长度为3的区间,
-
这道题目给人以区间dp的一种新的理解,不能过于拘泥在 枚举区间内中的分割点,还可以直接使用区间内某个特定的分割点,什么意思呢? - 只要左端点的颜色 == 右端点的颜色,合并左右区间的时候
-
可以直接转移左区间或者右区间,因为我们可以直接一刷子涂满整个区间
-
不需要任何花费就能向外拓展一个格子。
-
此时我们发现,我们可以把左右区间的颜色相等情况单独的分离出来,
-
即f [ i , j ] = min ( f [ i + 1 ] [ j ] , f [ i ] [ j -1 ] )
- 当左右区间的颜色不符合的时候,用你最拿手的状态转移方程式
- 即f [ i , j ] = min ( f [ i , j ] , f [ i , k ] + f [ k + 1 , j ] )

1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N=60; 4 char a[N]; 5 int f[N][N]; 6 7 int main() 8 { 9 10 scanf("%s",a+1); 11 int n=strlen(a+1); 12 memset(f,0x3f,sizeof f); 13 for(int len=1;len<=n;len++) 14 { 15 for(int i=1;i+len-1<=n;i++) 16 { 17 int j=len+i-1; 18 if(i==j) 19 { 20 f[i][j]=1; 21 continue; 22 } 23 if(a[i]==a[j])f[i][j]=min(f[i+1][j],f[i][j-1]); 24 else 25 { 26 for(int k=i;k<j;k++) 27 f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]); 28 } 29 } 30 } 31 32 printf("%d\n",f[1][n]); 33 34 return 0; 35 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!