Codeforces Round #538 (Div. 2)D. Flood Fill(区间DP)

题目链接:https://codeforces.com/contest/1114/problem/D

 

题目大意:给n个方块的颜色,相邻相同颜色的块可以同时变成另一种颜色,问所有的块变成一种颜色至少需要几次操作。

 

题目思路:dp[l][r][k]当k==0时,是l r区间内都是左端颜色的最小操作次数,k==1时是右端。转移方程就是看跟左右端比较情况。因为如果是这一段中的一个颜色跟它相同,而两边都不同,那就需要变两次,如果把里面变跟两边一样,然后把改颜色也变得跟两边一样,也是两次,不会影响结果,但要是跟两边颜色一样就能省一次

 

以下是代码:

#include
#include
#include
#include
#include
#include
using namespace std;
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
const int MAXN = 5005;
int n,a[MAXN],dp[MAXN][MAXN][2];
int main(){
    while(~scanf("%d",&n)){
        rep(i,1,n)scanf("%d",&a[i]);
        rep(i,1,n){
            rep(j,1,n){
                rep(k,0,1){
                    if(i==j)dp[i][j][k]=0;
                    else dp[i][j][k]=inf;
                }
            }
        }
        rep(r,1,n){
            per(l,r,1){
                rep(i,0,1){
                    int temp;
                    if(i==0)temp=a[l];
                    else temp=a[r];
                    if(l!=1)dp[l-1][r][0]=min(dp[l-1][r][0],dp[l][r][i]+(a[l-1]!=temp));
                    if(r!=n)dp[l][r+1][1]=min(dp[l][r+1][1],dp[l][r][i]+(a[r+1]!=temp));
                }
            }
        }
        printf("%d\n",min(dp[1][n][0],dp[1][n][1]));
    }
    return 0;
}

 

你可能感兴趣的:(动态规划)