CodeForces 1114DFlood Fill(区间DP)
题目链接:https://codeforces.com/problemset/problem/1114/D
题目大意:给出n个数字,从任意一个数字开始,将其变成左右相同的数字,最后所有数字相同,问最少变多少次
Examples
Input
4 5 2 2 1
Output
2
Input
8 4 5 2 2 1 3 5 5
Output
4
Input
1 4
Output
0
emmmm,区间DP,设置状态为dp[i][j],没什么好说的,比较普通,因为是相同的连续数字可以看出一块,所以我们首先可以直接将所有相同的连续数字合并,那么这样一来,每个数字的左邻右舍都是不同的数字了。接下来就是状态转移,对于区间$[l,r]$来讲,它是由区间$[l+1,r]$或者$[l,r-1]$转移过来的,那么转移的时候我们看看两边的数字是否一样,如果一样的话那么就没什么好说的了,直接:$dp[l][r]=dp[l+1][r-1]+1;$,否则的话我们就需要对两种转移状态取个最小值就OK了
以下是AC代码:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int mac=5e3+10; int color[mac],dp[mac][mac]; int main(int argc, char const *argv[]) { int n,pre=-1,cnt=0; scanf ("%d",&n); for (int i=1; i<=n; i++){ int x; scanf ("%d",&x); if (x!=pre) color[++cnt]=x; pre=x; } for (int len=2; len<=cnt; len++){ for (int l=1; l+len-1<=cnt; l++){ int r=l+len-1; if (color[l]==color[r]) dp[l][r]=dp[l+1][r-1]+1; else dp[l][r]=min(dp[l+1][r],dp[l][r-1])+1; } } printf("%d\n",dp[1][cnt]); return 0; }
路漫漫兮