保险箱的密码 【大红】
时间限制(普通/Java) : 1000 MS/ 3000 MS 运行内存限制 : 65536 KByte
总提交 : 118 测试通过 : 3
总提交 : 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 }