黑白翻转棋算法java实现_黑白翻转棋算法java实现

翻转游戏是在4*4的正方形里进行的,每个小正方形放有拥有黑白两面的棋子。每一轮你翻转3-5个棋子,把它从白变黑或从黑变白。

翻转的规则如下: 1. 选择任意一个棋子。 2. 翻转选择的棋子和与它相临的前后左右的棋子(如果有的话)

参考如下例子:

bwbw

wwww

bbwb

bwwb

其中 b表示黑色在上面,w表示白色在上面。如果选择第三行第一个棋子 进行翻转结果如下:

bwbw

bwww

wwwb

wwwb

游戏的目标在于使所有白色或所有黑色朝上,你的任务是计算完成目标所需要的最少步数。

[输入]

输入4行,每行4单词w或b,表示游戏初始格局。 [输出]:

输出完成目标所需最小步数。如果最初格局及达到目 标,输出0; 不能达到目标输出“Impossible”(不用引号)。 [样例]:

Sample Input :

bwwb

bbwb

bwww

Sample Output:

4

实际上我们完全可以只枚举第一行的操作,第一行有(翻,翻,翻,翻)(翻,翻,翻,不翻)。。。(不翻,不翻,不翻,不翻)16种,如果我们想把棋子全部翻成一种颜色的话,那么第二行的操作就是固定的了(因为第一行的 棋子的状态对第二行棋子的翻转进行了约束,如果想把第一行的棋子变成白色,那么第二行中位于第一行黑色棋子下方的位置必须翻转,反之亦然), 那么第三行、第四行的操作显然也是固定的了。

实现代码如下:

/** * */

/** *@author Administrator * */

package fanzhuanQi;

import java.util.Scanner;

public class fanzhuan{

static int steps=Integer.MAX_VALUE;

//(x,y)座标合起来就是中心点及上下左右座标啦!

static int [] dx={0,0,0,1,-1};

static int[] dy={0,1,-1,0,0};

/**    * 把每一行的状态和整个状态都以2进制表示,四个2进制数排成一行,组成整个状态。        * 1010       * 0000        * 1101   * 1001   *如图的状态表示为:1010000011011001   *@param x横座标点(注意:座标系右下为(0,0)左上为(3,3))        *@param y纵座标点   *@param source(整个状态如上面的1010000011011001)        *@return 改变确定位置的状态,如1变成0或者0变成1        */

public static int flip(int x,int y,int source)

{

if(x>=0&&x<4&&y>=0&&y<4)

source^=1<

return source;

}

/*  * @param current当前行 * @param num 回合数        * @param source 原数据,比如:1010000011011001        * @param flag 标志 如果数据源当前位的状态不为flag,则翻动       * */

public static void dfs(int current,int num,int source,int flag){

if(current==4)

{

if(source==0xFFFF||source==0)

{

//已经完成任务

steps=num

}

return ;

}

//把当前行都翻成同种颜色

int x,y;

for(int i=current-1,j=0;j<4;j++)//每行有4个,翻或者不翻共4种 ;翻动current行需要看current-1行的状态

{

if(((source&(1<>(i*4+j)^flag)==1){//判断当前行的j位置是否是flag标志,若不是则翻动

//source&(1<

for(int k=0;k<5;k++)//当前位置以及上下左右,5个位置翻动

{

x=current+dx[k];

y=j+dy[k];

source=flip(x, y, source);

}

num++;

}

}

dfs(current+1, num, source, flag);

}

/* 第一行共有16种翻法(翻,翻,翻,翻)(翻,翻,翻,不翻)。。。(不翻,不翻,不翻,不翻) * * */

public static int solve(int source)

{

for(int i=0;i<16;i++)

{

int num=0;

int temp=source;

int x,y;

for(int j=0;j<4;j++)

{

if((i&(1<0){

for(int k=0;k<5;k++){

x=0+dx[k];

y=j+dy[k];

temp=flip(x, y, temp);

}

num++;

}

}

dfs(1, num, temp, 0); //全部翻成白色

}

return steps==Integer.MAX_VALUE?-1:steps;

}

public static void main(String[] args)

{

Scanner scanner=new Scanner(System.in);

int source=0;

String string="";

for(int i=0;i<4;i++)

{

string+=scanner.nextLine().trim();

}

for(int i=0;i

{

source=(i==0?source:(source<<1))+(string.substring(i, i+1).equals("b")?1:0);

}

if(solve(source)!=-1)

{

System.out.println(steps);

}else{

System.out.println("Impossible");

}

}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值