区间DP(记搜)——BZOJ1032/Luogu2145 [JSOI2007]祖码Zuma
来源:互联网 发布:北京大学网络本科 编辑:程序博客网 时间:2024/06/05 14:45
题面:BZOJ1032 Luogu2145
一个很明显的区间DP
首先预处理,把相同颜色的连续珠子全部搞到一个数组段里去
v记录该段的数值,w记录该段的长度
定义状态:f[i][j]表示区间从i段到j段全部消掉所需最少珠子数
然后一个最显然最基础的状态转移方程:
f[i][j]=min(f[i][j],f[i][k]+f[k+1][j])
这是区间DP几乎必有的转移方程了吧,k从i到j-1枚举
然后就是边界条件和特殊处理的东西了
如果i=j,那么f[i][j]就是这一段要消掉的珠子数啦,题中有讲原来连三颗以上的珠子还需要一颗来激活,所以如果w>=3,f[i][j]=1,否则f[i][j]=2(加2颗凑到3颗)
然后还有一种情况,如果左端点颜色等于右端点颜色,那么f[i][j]=min(f[i][j],f[i+1][j-1]+(两边个数加起来个数是否大于2,是就不用加,不是就+1)
为什么呢,因为保证左右加起来个数肯定大于等于2
然后就可以DP了
这里给上记忆化搜索的代码,因为我感觉记忆化搜索比循环好理解。。。
#include<cstdio>#include<algorithm>#include<cmath>#include<cstring>#include<iostream>#include<cstdlib>#include<queue>#include<string>#include<ctime>#include<climits>using namespace std;int f[501][501];int n,m=0,a[1001];int v[1001],w[1001];inline int dfs(int l,int r){ if(f[l][r])return f[l][r]; if(l==r)return f[l][r]=w[l]>1?1:2; f[l][r]=1e9; if(v[l]==v[r]){ if(l+1==r)f[l][r]=1; else f[l][r]=dfs(l+1,r-1)+(w[l]+w[r]>2?0:1); } for(int i=l;i<r;i++)f[l][r]=min(f[l][r],dfs(l,i)+dfs(i+1,r)); return f[l][r];}int main(){ scanf("%d",&n);a[0]=-1; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); if(a[i]==a[i-1])w[m]++; else v[++m]=a[i],w[m]=1; } printf("%d",dfs(1,m)); return 0;}
阅读全文
1 0
- 区间DP(记搜)——BZOJ1032/Luogu2145 [JSOI2007]祖码Zuma
- bzoj1032 [JSOI2007]祖码Zuma DP
- bzoj1032: [JSOI2007]祖码Zuma
- bzoj1032: [JSOI2007]祖码Zuma
- bzoj1032: [JSOI2007]祖码Zuma
- bzoj 1032: [JSOI2007]祖码Zuma(区间DP)
- BZOJ 1032: [JSOI2007]祖码Zuma 区间DP
- SPOJ-ZUMA(区间DP)
- CF607B: Zuma(区间dp)
- HDU6212 Zuma(区间dp)
- [JSOI2007]祖码Zuma(洛谷2145)
- JSOI2007 祖码Zuma
- SPOJ 6340 ZUMA(区间DP)
- CodeForces 607 B. Zuma(区间DP)
- CodeForces 607B:Zuma(区间DP)
- Codeforces_607B:Zuma(区间DP)
- [JSOI2007]祖码Zuma/[bzoj]1032
- BZOJ 1032 [JSOI2007]祖码Zuma
- Netty心跳和重连
- 开发中遇到的坑
- Java简史
- java注解详解
- 功能强大的C语言memset()函数用法
- 区间DP(记搜)——BZOJ1032/Luogu2145 [JSOI2007]祖码Zuma
- 13.OP-TEE OS启动(四)--service_init_late
- AM335X SD卡分区制作
- java-反射
- 前端小知识
- DFS入门精讲:油田(Oil Deposits UVA572)
- ACM1001
- 计蒜客——草药的价值——背包问题
- thread