zoukankan      html  css  js  c++  java
  • NOJ 1111 保险箱的密码 【大红】 [区间dp]

    传送门

    保险箱的密码 【大红】

    时间限制(普通/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

    Accepted
    953MS
      724K
    2732Byte
    2015-02-10 10:20:01.0
    Time Limit Exceed at Test 1
       
    2724Byte
    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
    ",i,j,dp1[i][j],dp0[i][j],dp[i][j]);
    130         }
    131     }*/
    132     printf("%d
    ",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

    Accepted
    375MS
      724K
    2924Byte
    2015-02-10 10:48:12.0
    Wrong Answer at Test 1
       
    2738Byte
    2015-02-10 10:33:44.0
    Accepted
    953MS
      724K
    2732Byte
    2015-02-10 10:20:01.0
    Time Limit Exceed at Test 1
       
    2724Byte
    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
    ",i,j,dp1[i][j],dp0[i][j],dp[i][j]);
    136         }
    137     }*/
    138     printf("%d
    ",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 }
  • 相关阅读:
    C算法编程题系列
    C算法编程题(七)购物
    C算法编程题(六)串的处理
    C算法编程题(五)“E”的变换
    C算法编程题(四)上三角
    C算法编程题(三)画表格
    C算法编程题(二)正螺旋
    C算法编程题(一)扑克牌发牌
    我的编程开始(C)
    T-Sql学习系列完结
  • 原文地址:https://www.cnblogs.com/njczy2010/p/4283190.html
Copyright © 2011-2022 走看看