标签: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;
}
标签:first sizeof 就是 turn def val 区间 一个 ace
原文地址:https://www.cnblogs.com/EchoZQN/p/13255979.html