POJ 8496 特殊密码锁

特殊密码锁 问题描述:
有一种特殊的二进制密码锁,由n个相连的按钮组成(n<30),按钮有凹/凸两种状态,用手按按钮会改变其状态。
【POJ 8496 特殊密码锁】然而让人头疼的是,当你按一个按钮时,跟它相邻的两个按钮状态也会反转。当然,如果你按的是最左或者最右边的按钮,该按钮只会影响到跟它相邻的一个按钮。
当前密码锁状态已知,需要解决的问题是,你至少需要按多少次按钮,才能将密码锁转变为所期望的目标状态。
输入
两行,给出两个由0、1组成的等长字符串,表示当前/目标密码锁状态,其中0代表凹,1代表凸。
输出
至少需要进行的按按钮操作次数,如果无法实现转变,则输出impossible。
样例输入
011
000
样例输出
1
解题思路:本来还想从奇偶方面入手,但是发现自己想的太简单了,本来想根据0,1数量,从奇偶方面判断,后来试一试才发现,情况根本没那么简单。百度了一下,才知道贪心算法。先保证最后一位前面的数字都相同,不停按下按钮,如果到最后,最后一位也相同,则输出按下按钮的次数,否则输出Impossible。需要注意的一点就是,在前两个按钮不同的时候,是按第一个按钮,还是按第二个按钮,这个问题需要加以判断,若两种都可行,则最后需要输出按下次数最小的数值。

import java.util.Arrays; import java.util.Scanner; public class SpecialCodedLock {public static void main(String[] args) { // TODO Auto-generated method stub Scanner in = new Scanner(System.in); char[] s = in.nextLine().toCharArray(); char[] goal = in.nextLine().toCharArray(); int count = 0; int count_2 = 0; int result = -1; //第一种情况:前两个按钮不同,按下第二个按钮 char[] temp = Arrays.copyOf(s, s.length); for(int i = 1; i < goal.length; i++) { if(temp[i - 1] != goal[i - 1]) { push(temp, i); count++; } }//判断字符数组s与goal的最后一个字符是否相等 if(temp[temp.length - 1] == goal[goal.length - 1]) { result = 1; } else { count = (int) 1e9; }temp = Arrays.copyOf(s, s.length); //第二种情况:前两个按钮不同,按下第一个按钮 if(temp[0] != goal[0]) { temp[0] = temp[0] == '0' ? '1' : '0'; if(1 < s.length) temp[1] = temp[1] == '0' ? '1' : '0'; count_2++; }for(int i = 2; i < goal.length; i++) { if(temp[i - 1] != goal[i - 1]) { push(temp, i); count_2++; } }if(temp[temp.length - 1] == goal[goal.length - 1]) { result = 1; } else { count_2 = (int) 1e9; }//如果result等于-1,则无法转变为目标字符串 if(result != -1) { System.out.println(count > count_2 ? count_2 : count); } else { System.out.println("impossible"); } }//改变按下按钮的前后及自身的值 public static void push(char[] temp, int i) { temp[i] = temp[i] == '0' ? '1' : '0'; temp[i - 1] = temp[i - 1] == '0' ? '1' : '0'; if(i + 1 < temp.length) temp[i + 1] = temp[i + 1] == '0' ? '1' : '0'; } }

    推荐阅读