P4170 [CQOI2007]涂色
Posted hexqwq
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4170 [CQOI2007]涂色相关的知识,希望对你有一定的参考价值。
先看一下题意:
? 给你一个 n 长度的木板,刚开始是没有颜色的,现在你需要用最少的涂色次数,让这个木板的颜色变成给定的目标颜色
解析
读懂题意,发现这是一个求处理一个区间的最小操作数的题目,这时候就要考虑能不能用区间DP处理这个题目,一般来说,区间DP的时间复杂度为 (n^3)或 (n^2),本题 n 最大仅 50 ,在时间复杂度上满足要求。
在确定题目是区间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]) ]
以上就是本题的解释。在写区间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; }
以上是关于P4170 [CQOI2007]涂色的主要内容,如果未能解决你的问题,请参考以下文章