码迷,mamicode.com
首页 > 其他好文 > 详细

区间dp [D - Flood Fill] 暑训第四天

时间:2020-07-06 18:12:17      阅读:59      评论:0      收藏:0      [点我收藏+]

标签:first   sizeof   就是   turn   def   val   区间   一个   ace   

区间dp D - Flood Fill

题目大意:

如果[l,r] 这个连续的区间的数都相等,则说明这个是一个连通块,给你n个数,每一个数都代表这个位置的颜色,首先你要选取第一个操作的位置,之后你可以对这个位置所在的连通块进行改变颜色,可以改变成任意颜色。问最少多少次操作可以让这n个数变成一个颜色。

题解:

首先要重视这个操作的位置只有一个,就是最开始选取的。

使得 \([l,r]\) 这个区间最后都是一样的颜色,那么只能从 \([l+1,r]\) \([l,l]\) 和 $[l,r-1] $ $ [r,r]$这两个状态转移过来。

我们可以假设第一个选取的位置在 \([l+1,r]\) 或者 \([l,r-1]\),那么 \([l,l]\) 或者 \([r,r]\) 则是要变成的颜色,那么最后\([l,r]\) 这个区间的颜色就是 \([l,l]\) 或者 \([r,r]\)

如果是从 \([l+1,r]\) 这个状态转移过来,那么最后这个颜色应该是和 \(l\) 这个位置的颜色是一样的。

如果是从 \([l,r-1]\) 这个状态转移过来,那么最后这个颜色应该是和 \(r\) 这个位置的颜色是一样的。

所以需要第三维,对于区间 \([l,r]\) 0表示从 \(l\) 转移过来,1表示从 \(r\) 转移过来。

#include <bits/stdc++.h>
#define id first
#define val second
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn=5e3+10;
int dp[maxn][maxn][2],a[maxn];

int main(){
    int n;
    scanf("%d",&n);
    memset(dp,inf,sizeof(dp));
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),dp[i][i][0]=dp[i][i][1]=0;
    for(int len = 2;len<=n;len++){
        for(int i=1;i+len-1<=n;i++){
            int j=i+len-1;
            dp[i][j][0]=min(dp[i+1][j][1]+(a[j]!=a[i]),dp[i+1][j][0]+(a[i+1]!=a[i]));
            dp[i][j][1]=min(dp[i][j-1][0]+(a[j]!=a[i]),dp[i][j-1][1]+(a[j-1]!=a[j]));
        }
    }
    printf("%d\n",min(dp[1][n][0],dp[1][n][1]));
    return 0;
}

区间dp [D - Flood Fill] 暑训第四天

标签:first   sizeof   就是   turn   def   val   区间   一个   ace   

原文地址:https://www.cnblogs.com/EchoZQN/p/13255979.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!