(枚举)8469:特殊密码锁

问题描述 
有一种特殊的二进制密码锁,由n个相连的按钮组成(n<30),按钮有凹/凸两种状态,用手按按钮会改变其状态。然而让头疼的是,当你按一个按钮时,跟它相邻的两个按钮状态也会反转。当然,如果你按的是最左或者最右边的按钮,该按钮只会影响到跟它相邻的一个按钮。当前密码锁状态已知,需要解决的问题是,你至少需要按多少次按钮,才能将密码锁转变为所期望的目标状态。 


输入 
两行,给出两个由0、1组成的等长字符串,表示当前/目标密码锁状态,其中0代表凹,1代表凸。 


输出 
至少需要进行的按按钮操作次数,如果无法实现转变,则输出 impossible。 


样例输入 
011 
000 


样例输出 
1

 

我の思考

此题想要用枚举法来解决,那我们就应该找出可能的几种情况。我们研究过这个机制后会发现,影响按钮改变的其实就是周围的按钮。但是在这里,我们会发现,第一个按钮的按与否,会影响到后面所有的按钮,也就是说,这里的枚举是枚举出当按下第一个按钮和不按第一个按钮的情况。而其他的,就只要找到一个不和目标对应为相等的按钮,我们按下它的下一个即可。

 

我の代码

#include <iostream>
#include <stdlib.h>
#include <string.h>
using namespace std;
int result=1<<30;
int result2=0;
int len=0; void flipNum(char* a,int i){ if(a[i] == '1'){ a[i] ='0'; } else { a[i] = '1'; } } //比较是否相同 int cmpNum(char* a,char* b){ int i=0; for(;i<len;i++){ if(a[i]!=b[i]){ return false; } } return true; } //设置反转 void setArray(char* a,int i){ flipNum(a,i); if(i == 0){ flipNum(a,i+1); } else { flipNum(a,i-1); flipNum(a,i+1); } result2++; } //获取次数最小的 int minNum(int i,int j){ if(i<j) return i; else return j; } int main() { char origin[35]; char aim[35]; cin>>origin; cin>>aim; len = strlen(origin); //处理数据 if(cmpNum(origin,aim)){ result = minNum(result,result2); return 0; } char c[35]; for(int p=0;p<2;p++){ result2=0; memcpy(c,origin,len); if(p==1){ setArray(c,0); if(cmpNum(c,aim)){ result = minNum(result,result2); } } for(int i=0;i<len-1;i++){ if(c[i] != aim[i]){ setArray(c,i+1); if(cmpNum(c,aim)){ result = minNum(result,result2); } } } } if(result == 1<<30) cout<<"impossible"; else cout << result; return 0; }

我の小结

此外,因为我也算是一个算法学习上的新人,在很多细节处理的地方都不好。通过这个例子,我应该注意到,如果是最小的次数,一定要记得把所有的情况都经历过一次,再取最小的。还有数组设置长度的时候,最好设大一点点,可以提高容纳错误的能力,另外就是一些常用函数的对应头文件啊之类的要记忆一下QAQ。

转载于:https://www.cnblogs.com/rimochiko/p/7486925.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值