python翻转棋_Python算法做翻转棋子游戏

2020-08-30 20:15:35

我分别用穷举和回溯两种算法来实现这个功能,代码如下:

#穷举法:直接用位运算操作整数t的各个二进制数位,效率更高

def divide_stones_4(a, n):

total = sum(a)

half = total // 2

max_s = 0

lib = tuple(map(lambda x: 1 << x, range(n-1,-1,-1)))#从高到低标记每个二进制位的1

for t in range(1<

s = 0

for i in range(n):

if t & lib[i] > 0: #t的二进制数第i位是1,则选择该堆石子

s += a[i]      #累计被选中的石子堆的数量

if max_s < s <= half: #更新最优解

max_s = s

return total - max_s * 2 #返回最小差值

#深搜算法:直接用位运算操作整数t的各个二进制数位,每层递归函数的选择模式都继承自上一层函数,每层只选择1堆石子

def divide_stones_5(a, n):

total = sum(a)

half = total // 2

max_s = 0

lib = tuple(map(lambda x: 1 << x, range(n-1,-1,-1)))#从高到低标记每个二进制位的1

def dfs(t, s): #参数:t,正整数,其二进制数代表当前选择模式;s,正整数,表示已经选择的石子数量。

nonlocal max_s

if s > max_s: #更新最优解

max_s = s

for i, bit in enumerate(lib):

if t & bit == 0:     #只在第一个值为1的二进制位左侧设置1,以避免重复

if s+a[i] <= half:  #已经超出半数就无需再选择新的石子堆了

t |= bit     #将整数t的第i个二进制位设置成1

dfs(t, s+a[i])

t &= ~bit    #将整数t的第i个二进制位恢复成0

else:

break

dfs(0, 0)

return total - max_s * 2 #返回最小差值

在穷举算法中,无论是用列表b来模拟一个整数t的n位二进制数,还是用位运算直接操作整数t的各个二进制位,都是非常巧妙的方法,每当遇到这种题目,都有令人眼前一亮的感觉。无独有偶,我有幸遇到了与“石子划分问题”很相似的一道题目,与大家共同分享。

题目:翻转棋子游戏

难度:3星      有趣:3星    有用:3星

分类:穷举,深搜,广搜

描述:翻转棋子游戏是这样玩的:

有一张4*4的棋盘,在16个位置上每个位置放着一个棋子,棋子一面是黑色,另一面是白色,棋子或者白色面朝上,或者黑色面朝上。

游戏的走法如下:每一步先选择一个位置,然后把该位置和上,下,左,右(不越界)相邻位置上的棋子翻转(白->黑,黑->白)。

我们用一个长度为16的字符串board存储棋盘上每颗棋子的颜色状态,每颗棋子的颜色可以用0、1来表示,0表示白,1表示黑,顺序为从左至右,从上至下。

例如,board="1011000111110001",表示的棋盘状态如下:

1010

0000

1101

1001

当我们选择第三行,第一列的位置翻转时,棋盘变化为:

1010

1000

0001

0001

游戏的目的是用最少的步数把全部棋子变为白色向上或黑色向上。

函数:flip_chess(board)

参数说明:board -- 长度为16的字符串,存储了棋盘上每颗棋子的初始颜色状态。

返回值:返回最少的翻转次数,如果无法翻转成目标状态,则输出"impossible"。

样例1: board="1010000011011001",返回"impossible";

样例2: board="1001110110011000",返回4。

算法分析:

初看本题,最容易想到的是穷举法,用包含16个元素的列表d分别表示每个棋子的翻转状态,d[i]=1表示翻转第i个棋子,d[i]=0表示不翻转。

可以穷举从d=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]到d=[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],即从都不翻转到都翻转。若把列表d对应整数t的16位二进制数,则相当于穷举从t=0到t=2^16-1。

我们可以直接用位运算操作整数t的各个二进制数位,从而生成整数t对应的棋盘翻转模式,判断该模式是否有解。若该翻转模式能获得更好的解,则更新最优解。

本题的各种算法也可以用c++语言来实现,两种语言相比较,我发现由于Python语言的自动回收内存机制和函数式编程特征,以及丰富的内置函数,使得编程者无需考虑过多的实现细节,能更关注算法思想本身,代码也更简洁,更优雅。

----------------------------------------------

相关文章

更多文章

.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值