这么简单的区间dp我居然写挂了嘤嘤嘤
题解
主要是分为两种情况:
-
定义 \(dp[i][j]\) 为区间 \([i,j]\) 内最少涂色次数,下面考虑转移
-
首先考虑区间两边颜色相同的情况,我们只需要考虑将区间缩小一格时次数最少就可以了,即
\(dp[i][j]=min \{dp[i+1][j],dp[i][j-1]\}\)注意:不可以写为 \(dp[i+1][j-1]+1\) ,这种情况没有考虑到 \(i+1\) 或 \(j-1\) 位置上也是颜色相同
-
再考虑两侧颜色不同的情况。如果颜色不同,则需要枚举中间位置找出一个最优的位置即可。因为如果是将两侧颜色相同的包括了的话,一定已经算过了,在之前或之后的某处一定会算进去的
-
处置设为正无穷,但 \(dp[i][i]\) 置为 \(0\)
#include <bits/stdc++.h>
using namespace std;
int n;
const int maxn=302;
int f[maxn][maxn],c[maxn];
int main()
{
// freopen("paint.in","r",stdin);
// freopen("paint.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&c[i]);
memset(f,0x3f,sizeof(f));
for(int i=1;i<=n;i++)
f[i][i]=1;
for(int l=2;l<=n;l++)
{
for(int i=1;i+l-1<=n;i++)
{
int j=i+l-1;
if(c[i]==c[j])
{
f[i][j]=min(f[i][j],min(f[i+1][j],f[i][j-1]));
}
else
{
for(int k=i;k<=j;k++)
{
f[i][j]=min(f[i][k-1]+f[k][j],f[i][j]);
}
}
}
}
printf("%d",f[1][n]);
}