bzoj1032
这道题noip之前就在写了,但是奈何自己太弱了,对于dp的感觉不是特别~~♂。(偷偷瞄了一眼题解,绝对没有第二眼)
这道题是区间dp无疑,预处理连续的颜色一样的,f[i][j]表示区间i到区间j消去的最小代价方程:f[i][j]=min(f[i][j],f[i][k]+f[k+1][j])
然后要特判一下i和j颜色一样的情况.
#include <stdio.h> #include <algorithm> #include <cstring> #include <cmath> #include <queue> #include <vector> using namespace std; const int maxn=500+10; int n,cnt; int num[maxn],color[maxn],f[maxn][maxn]; template <class T> void read(T&x) { x=0;char c=getchar();int f=0; while(c<'0'||c>'9'){f|=(c=='-');c=getchar();} while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar(); x=f?-x:x; } int main() { read(n); int x; for(register int i=1;i<=n;i++) { int y=x;read(x); if(y!=x||i==1)color[++cnt]=x,num[cnt]=1; else num[cnt]++; } n=cnt; memset(f,0x7f/5,sizeof(f)); for(int i=1;i<=n;i++)f[i][i]=num[i]==1?2:1; for(int len=2;len<=n;len++) for(int i=1;i+len-1<=n;i++) { int j=i+len-1; for(int k=i;k<=j;k++)f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]); if(color[i]==color[j]) { if(num[i]+num[j]>=3)f[i][j]=min(f[i][j],f[i+1][j-1]); else f[i][j]=min(f[i][j],f[i+1][j-1]+1); } } printf("%d",f[1][n]); return 0; }