题目大意:给定一个祖玛序列,任选颜色射♂出珠子,问最少射♂出多少珠子
输入法最近越来越奇怪了0.0
首先我们把连续相同的珠子都缩在一起 令f[i][j]表示从i开始的j个珠子的最小消除次数
初值 f[i][1]=cnt[i]==1?2:1
然后对于每个区间,我们枚举中间点,拆成两半求和
如果这个区间两端点颜色相同,我们还可以把中间消掉,然后两边再补射1或0个
尼玛珠子的颜色可以是0……因为这个WA了半天 真~!@#$%^&*()
此外此题是有BUG的 我的代码不能考虑将三个离散的珠子 聚在一起的情况 但是AC了
例:
7
1 2 2 1 3 3 1
ans:2
因此我又写了第二个版本,在区间两侧的珠子都是单个的时候去区间内部寻找第三个单个的珠子,结果数据原因WA掉了,但是确实可以过这组数据
希望官方可以把数据更新一下~(@^_^@)~
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 510 using namespace std; int n; pair<int,int>a[M]; int f[M][M]; int main() { int i,j,k,x; cin>>n; a[0].first=19980402; for(i=1,j=0;i<=n;i++) { scanf("%d",&x); if(x!=a[j].first) a[++j].first=x; a[j].second++; } n=j; memset(f,0x3f,sizeof f); for(i=1;i<=n;i++) f[i][1]=a[i].second==1?2:1; for(j=2;j<=n;j++) for(i=1;i+j-1<=n;i++) { if(a[i].first==a[i+j-1].first) f[i][j]=f[i+1][j-2]+(a[i].second+a[i+j-1].second==2?1:0); for(k=1;k<j;k++) f[i][j]=min(f[i][j],f[i][k]+f[i+k][j-k]); } cout<<f[1][n]<<endl; }
能过那组数据但是WA掉的代码
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 510 using namespace std; int n; pair<int,int>a[M]; int f[M][M]; int main() { int i,j,k,x; cin>>n; a[0].first=19980402; for(i=1,j=0;i<=n;i++) { scanf("%d",&x); if(x!=a[j].first) a[++j].first=x; a[j].second++; } n=j; memset(f,0x3f,sizeof f); for(i=1;i<=n;i++) f[i][1]=a[i].second==1?2:1; for(j=2;j<=n;j++) for(i=1;i+j-1<=n;i++) { if(a[i].first==a[i+j-1].first) { if(a[i].second+a[i+j-1].second==2) { f[i][j]=f[i+1][j-2]+1; for(k=2;k<j;k++) if(a[i+k-1].first==a[i].first&&a[i+k-1].second==1) f[i][j]=min(f[i][j],f[i+1][k-2]+f[i+k][j-k-1]); } else f[i][j]=f[i+1][j-2]; } for(k=1;k<j;k++) f[i][j]=min(f[i][j],f[i][k]+f[i+k][j-k]); } cout<<f[1][n]<<endl; }
BZOJ 1032 JSOI2007 祖码Zuma 动态规划
原文地址:http://blog.csdn.net/popoqqq/article/details/40581599