传送门

保险箱的密码 【大红】

时间限制(普通/Java) :  1000 MS/  3000 MS           运行内存限制 : 65536 KByte
总提交 : 118            测试通过 : 3 

题目描述

最近sed同学设计了一套保险箱密码锁,密码锁上有依次排好的0、1数字键,保险箱密码是由0和1组成的数字串。开启这个保险箱需要正确的密码,还需要将密码锁上数字键设定为对应的0或1,而这个过程需要特定的技巧:每次变换的工作:将密码锁上连续的0、1数字串用同样数目的全0或全1数字串代替。现给你正确的密码 (不超过200),请计算开启这个保险箱,最少需要经过多少次变换。

输入

第一行是一个正整数:测试用例数目,最多为100。之后,每个测试用例包括两行:

l       第1行给出密码锁上初始的0、1数字串(不超过200)

l       第2行给出保险箱的正确密码

输出

对于每个测试用例:

l       开启保险箱需要的最少变换数

样例输入

2
000
111
1011
0010

样例输出

1
2

题目来源

“IBM南邮杯”团队赛2009

njczy2010
1111
Accepted
953MS
724K
2732Byte
G++
2015-02-10 10:20:01.0
njczy2010
1111
Time Limit Exceed at Test 1
   
2724Byte
G++
2015-02-10 10:18:11.0

题解:

区间dp

对于 i-j的区间,整个区间置0或置1,至多只会出现一次
因为你如果再置,就会把前面的操作覆盖,没有意义
所以,下面的操作长度,必然都小于 i-j

同时可以证明,重叠的区间操作也是没有意义的,同理:会覆盖前面的某些操作
所以,可以不断把区间缩小

加上记忆化就可以水过了,不过应该还有更加优化的方法,有待思考。

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<cstdio>
  5 #include<algorithm>
  6 #include<cmath>
  7 #include<queue>
  8 #include<map>
  9 #include<set>
 10 #include<stack>
 11 #include<string>
 12
 13 #define N 205
 14 #define M 105
 15 #define mod 10000007
 16 //#define p 10000007
 17 #define mod2 1000000000
 18 #define ll long long
 19 #define LL long long
 20 #define eps 1e-6
 21 #define inf 100000000
 22 #define maxi(a,b) (a)>(b)? (a) : (b)
 23 #define mini(a,b) (a)<(b)? (a) : (b)
 24
 25 using namespace std;
 26
 27 int T;
 28 char s[N];
 29 char t[N];
 30 int dp[N][N];
 31 int dp1[N][N];
 32 int dp0[N][N];
 33 int le;
 34 int ans;
 35
 36 int fun(int l,int r);
 37 int fun0(int l,int r);
 38 int fun1(int l,int r);
 39
 40 void ini()
 41 {
 42     memset(dp,-1,sizeof(dp));
 43     memset(dp1,-1,sizeof(dp1));
 44     memset(dp0,-1,sizeof(dp0));
 45     scanf("%s",s+1);
 46     scanf("%s",t+1);
 47     le=strlen(s+1);
 48 }
 49
 50 int fun1(int l,int r)
 51 {
 52     if(dp1[l][r]!=-1) return dp1[l][r];
 53     int re;
 54     int st=l;
 55     int en=r;
 56     for(st=l;st<=r;st++){
 57         if(t[st]=='0') break;
 58     }
 59     if(st>r) return dp1[l][r]=0;
 60     for(en=r;en>=st;en--){
 61         if(t[en]=='0') break;
 62     }
 63     if(st==en){
 64         return dp1[l][r]=1;
 65     }
 66     re=fun0(st,en)+1;
 67     dp1[l][r]=re;
 68     return re;
 69 }
 70
 71 int fun0(int l,int r)
 72 {
 73     if(dp0[l][r]!=-1) return dp0[l][r];
 74     int st=l;
 75     int en=r;
 76     int re;
 77     for(st=l;st<=r;st++){
 78         if(t[st]=='1') break;
 79     }
 80     if(st>r) return dp0[l][r]=0;
 81     for(en=r;en>=st;en--){
 82         if(t[en]=='1') break;
 83     }
 84     if(st==en){
 85         return dp0[l][r]=1;
 86     }
 87     re=fun1(st,en)+1;
 88     dp0[l][r]=re;
 89     return re;
 90 }
 91
 92 int fun(int l,int r)
 93 {
 94     if(dp[l][r]!=-1) return dp[l][r];
 95     int st=l;
 96     int en=r;
 97     for(st=l;st<=r;st++){
 98         if(s[st]!=t[st]) break;
 99     }
100     if(st>r) return dp[l][r]=0;
101     for(en=r;en>=st;en--){
102         if(s[en]!=t[en]) break;
103     }
104     if(st==en){
105         return dp[l][r]=1;
106     }
107     int i;
108     int re=1000000000;
109     for(i=st+1;i<=en;i++){
110         re=min(re,fun(st,i-1)+fun(i,en));
111     }
112     re=min(re,fun1(st,en)+1);
113     re=min(re,fun0(st,en)+1);
114     dp[l][r]=re;
115     return re;
116 }
117
118 void solve()
119 {
120     ans=fun(1,le);
121 }
122
123 void out()
124 {
125     /*
126     int i,j;
127     for(i=1;i<=le;i++){
128         for(j=i;j<=le;j++){
129             printf(" i=%d j=%d dp1=%d dp0=%d dp=%d\n",i,j,dp1[i][j],dp0[i][j],dp[i][j]);
130         }
131     }*/
132     printf("%d\n",ans);
133 }
134
135 int main()
136 {
137     //freopen("data.in","r",stdin);
138     //freopen("data.out","w",stdout);
139     scanf("%d",&T);
140     //for(int ccnt=1;ccnt<=T;ccnt++)
141     while(T--)
142     //scanf("%d%d",&n,&m);
143     //while(scanf("%s",s)!=EOF)
144     {
145         ini();
146         solve();
147         out();
148     }
149     return 0;
150 }

继续思考,将区间分成两部分时,原串和正确串已经相同的部分可以跳过,故可以减少好多操作,当成剪枝1

njczy2010
1111
Accepted
375MS
724K
2924Byte
G++
2015-02-10 10:48:12.0
njczy2010
1111
Wrong Answer at Test 1
   
2738Byte
G++
2015-02-10 10:33:44.0
njczy2010
1111
Accepted
953MS
724K
2732Byte
G++
2015-02-10 10:20:01.0
njczy2010
1111
Time Limit Exceed at Test 1
   
2724Byte
G++
2015-02-10 10:18:11.0
  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<cstdio>
  5 #include<algorithm>
  6 #include<cmath>
  7 #include<queue>
  8 #include<map>
  9 #include<set>
 10 #include<stack>
 11 #include<string>
 12
 13 #define N 205
 14 #define M 105
 15 #define mod 10000007
 16 //#define p 10000007
 17 #define mod2 1000000000
 18 #define ll long long
 19 #define LL long long
 20 #define eps 1e-6
 21 #define inf 100000000
 22 #define maxi(a,b) (a)>(b)? (a) : (b)
 23 #define mini(a,b) (a)<(b)? (a) : (b)
 24
 25 using namespace std;
 26
 27 int T;
 28 char s[N];
 29 char t[N];
 30 int dp[N][N];
 31 int dp1[N][N];
 32 int dp0[N][N];
 33 int le;
 34 int ans;
 35
 36 int fun(int l,int r);
 37 int fun0(int l,int r);
 38 int fun1(int l,int r);
 39
 40 void ini()
 41 {
 42     memset(dp,-1,sizeof(dp));
 43     memset(dp1,-1,sizeof(dp1));
 44     memset(dp0,-1,sizeof(dp0));
 45     scanf("%s",s+1);
 46     scanf("%s",t+1);
 47     le=strlen(s+1);
 48 }
 49
 50 int fun1(int l,int r)
 51 {
 52     if(dp1[l][r]!=-1) return dp1[l][r];
 53     int re;
 54     int st=l;
 55     int en=r;
 56     for(st=l;st<=r;st++){
 57         if(t[st]=='0') break;
 58     }
 59     if(st>r) return dp1[l][r]=0;
 60     for(en=r;en>=st;en--){
 61         if(t[en]=='0') break;
 62     }
 63     if(st==en){
 64         return dp1[l][r]=1;
 65     }
 66     re=fun0(st,en)+1;
 67     dp1[l][r]=re;
 68     return re;
 69 }
 70
 71 int fun0(int l,int r)
 72 {
 73     if(dp0[l][r]!=-1) return dp0[l][r];
 74     int st=l;
 75     int en=r;
 76     int re;
 77     for(st=l;st<=r;st++){
 78         if(t[st]=='1') break;
 79     }
 80     if(st>r) return dp0[l][r]=0;
 81     for(en=r;en>=st;en--){
 82         if(t[en]=='1') break;
 83     }
 84     if(st==en){
 85         return dp0[l][r]=1;
 86     }
 87     re=fun1(st,en)+1;
 88     dp0[l][r]=re;
 89     return re;
 90 }
 91
 92 int fun(int l,int r)
 93 {
 94     if(dp[l][r]!=-1) return dp[l][r];
 95     int st=l;
 96     int en=r;
 97     for(st=l;st<=r;st++){
 98         if(s[st]!=t[st]) break;
 99     }
100     if(st>r) return dp[l][r]=0;
101     for(en=r;en>=st;en--){
102         if(s[en]!=t[en]) break;
103     }
104     if(st==en){
105         return dp[l][r]=1;
106     }
107     int re=1000000000;
108     int en1,st2;
109     for(en1=st;en1<=en-1;en1++){
110         if(s[en1]==t[en1]) continue;
111         for(st2=en1+1;st2<=en;st2++){
112             if(s[st2]==t[st2]) continue;
113             re=min(re,fun(st,en1)+fun(st2,en));
114             en1=st2-1;
115             break;
116         }
117     }
118     re=min(re,fun1(st,en)+1);
119     re=min(re,fun0(st,en)+1);
120     dp[l][r]=re;
121     return re;
122 }
123
124 void solve()
125 {
126     ans=fun(1,le);
127 }
128
129 void out()
130 {
131     /*
132     int i,j;
133     for(i=1;i<=le;i++){
134         for(j=i;j<=le;j++){
135             printf(" i=%d j=%d dp1=%d dp0=%d dp=%d\n",i,j,dp1[i][j],dp0[i][j],dp[i][j]);
136         }
137     }*/
138     printf("%d\n",ans);
139 }
140
141 int main()
142 {
143     //freopen("data.in","r",stdin);
144     //freopen("data.out","w",stdout);
145     scanf("%d",&T);
146     //for(int ccnt=1;ccnt<=T;ccnt++)
147     while(T--)
148     //scanf("%d%d",&n,&m);
149     //while(scanf("%s",s)!=EOF)
150     {
151         ini();
152         solve();
153         out();
154     }
155     return 0;
156 }

转载于:https://www.cnblogs.com/njczy2010/p/4283190.html

NOJ 1111 保险箱的密码 【大红】 [区间dp]相关推荐

  1. HDU 5968 异或密码(区间dp)

    Problem Description 晨晨在纸上写了一个长度为N的非负整数序列{ai}.对于这个序列的一个连续子序列{al,al+1,-,ar}晨晨可以求出其中所有数异或的结果 alxoral+1x ...

  2. 1222. 密码脱落 区间dp

    密码脱落 X星球的考古学家发现了一批古代留下来的密码. 这些密码是由A.B.C.D 四种植物的种子串成的序列. 仔细分析发现,这些密码串当初应该是前后对称的(也就是我们说的镜像串). 由于年代久远,其 ...

  3. 区间DP小结(附经典例题)

    写这篇文章的目的主要是想总结下区间DP的经典题目,同时给自己复习巩固这方面知识点. 区间DP 一.定义 ​ 区间DP是线性动态规划的扩展,适用场景为每段区间的最优解可以通过更小区间的最优解得到.所以我 ...

  4. 刷题周记(八)——#区间DP:多边形、清空字符串 #状态机:股票买卖I~V、大盗阿福

    文章目录 --2020年12月13日(周日)------------------ #区间DP 一.多边形 --2020年12月14日(周一)------------------ --2020年12月1 ...

  5. nyoj 304 节能 【区间dp】

    点击打开链接 节能 时间限制:1000 ms  |  内存限制:65535 KB 难度:5 描述 Dr.Kong设计的机器人卡多越来越聪明.最近市政公司交给卡多一项任务,每天早晨5:00开始,它负责关 ...

  6. POJ 2955 Brackets (区间DP)

    题目链接:http://poj.org/problem?id=2955 Brackets Time Limit: 1000MS   Memory Limit: 65536K Total Submiss ...

  7. 0x53. 动态规划 - 区间DP(习题详解 × 8)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 文章目录 0x53. 动态规划 - 区间DP Problem A. 最优矩阵链乘 Problem B. ...

  8. UVA1626 括号序列 Brackets sequence(区间DP匹配括号,输出匹配方案)

    整理的算法模板合集: ACM模板 UVA1626 Brackets sequence 我们将正规括号序列定义如下: 空序列是正规括号序列. 如果 SSS 是一个正规括号序列,那么 (S) 和 [S] ...

  9. UVA10003 切木棍 Cutting Sticks(区间DP、细节)

    整理的算法模板合集: ACM模板 本题其实就是一个区间DP 的模板题,总长度为len,有n个切割点,也就是说能被切割成n+1段,所以左边界是0,有边界是n + 1,所以答案就是f[0][n + 1]. ...

最新文章

  1. C++中struct的使用
  2. 英文字典设计c语言代码,一种简单的英文词典排版系统
  3. 皮一皮:碰上一个说倒装句的直男怎么办...
  4. 01_SMC_Calling_Convention(SMCCC)
  5. 2020年12月份学习总结,PMP与信息系统项目管理师的回顾
  6. SpringCloud基本模块分配搭建以及负载均衡
  7. Qt下Tcp传输文件
  8. 如何评价分类模型性能?(足球荔枝)
  9. 计算机专业的求职信英文作文,计算机专业本科英文求职信范文
  10. Http长连接的例子_亲测可用哦
  11. 飞鸽传书2011帮助文档
  12. arduino和单片机c语言,Arduino和单片机的区别-与非网
  13. mysql in 索引_关于MySQL种的in函数到底走不走索引、我和同事差点大打出手!
  14. python引入redis_实操演练解读非关系型数据库—Redis
  15. mysql innodb 多核cpu_没有改变,但MySQL InnoDB超载CPU
  16. 算法设计与分析期末复习题(史上最详细)
  17. 使用layui的laypage完成分页
  18. 谷歌浏览器控制台使用
  19. 王石:中国楼市泡沫必破 目前只是时间问题
  20. 我常用的网站资源集合

热门文章

  1. 中国航天日,主题是“格物致知,叩问苍穹”
  2. windows10 + GUDA9.0+cudnn7.0.5+GPU+Visual studio2013
  3. python GDAL遥感影像云优化(COG)
  4. 关于generate用法的总结【Verilog】
  5. PHP socket多路复用通信demo
  6. 团队项目(第四周之一)—GG队
  7. RDD的执行流程(简略)
  8. HTML DOM firstChild lastChild nextSibling previousSibling 属性_获取属性值的undefined问题
  9. Stata:自己动手做组间系数差异检验-bootstrap-bdiff
  10. fortran语言和python语言_fortran语言还有人用吗