[JSOI2007]祖玛
做题时间:2022.9.28
给定一排 个整数,可以向之间插入任意一个整数,得到相邻的多于2个相同的整数就可以把他们消除掉,其余整数按顺序合并起来,也可以继续消除(一开始就连续的3个及以上的整数是不能消除的),问最少插入多少个整数使得所有整数都被消除完。
第一行一个整数
第二行 个整数
一行一个整数表示答案
区间dp
消除后剩余的整数连接成一个连续的区间,因此可以使用区间dp,首先可以将原序列相邻的相同的整数合并到 和 中( 表示数的大小, 表示数的个数),定义 表示消除 的最小代价。首先,可以通过两个区间消除合并得到,即:
其次,若 ,表示 这一段消除后可以合并 再进行消除,即:
#include<cstdio> #include<iomanip> #include<cstring> using namespace std; const int N=550; int f[N][N],a[N],n; int s[N],cnt[N],ed; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); s[++ed]=a[1],cnt[1]=1; for(int i=2;i<=n;i++){ if(a[i]==a[i-1]) cnt[ed]++; else{ s[++ed]=a[i]; cnt[ed]=1; } } memset(f,63,sizeof f); for(int i=1;i<=ed;i++){ if(cnt[i]>1) f[i][i]=1; else f[i][i]=2; } for(int len=2;len<=ed;len++){ for(int i=1;i<=ed-len+1;i++){ int j=i+len-1; if(s[i]==s[j]) f[i][j]=min(f[i][j],f[i+1][j-1]+(cnt[i]+cnt[j]<=2)); for(int k=i;k<j;k++){ f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]); } } } if(f[1][ed]==3) printf("2\n"); else printf("%d\n",f[1][ed]); return 0; }
本文作者:lxzy
本文链接:https://www.cnblogs.com/Unlimited-Chan/p/16740706.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步