选球博奕与动态规划(四)

        这里不严格展开,只简单分析一下算法SOLVE的时间复杂度。由于此算法是基于递归公式A的,假设对任一局面N有Cond(N) = Vol(N)-1 则可将公式展开为:

        

        

        

        

        ......

       

        因此, ,这一效率不理想。

       实际上,从题目的要求可知,假设球的总数为M,那么首轮决策取球数不应该超过low(M/2),low()为向下取整函数;如果M为偶数的话首轮取球数最多为:M/2-1。否则的话,按游戏规则,最后一个球一定会被对方取走。因此判断一个局面N是否有解,只要考虑子局面Ci(N)解的情况,其中1≤ i ≤low(Vol(N)/2),或考虑局面所有球是否可以被当前决策方全取走,即可。为此得到以下新算法:

SOLVE_OPT(m, cnd)
  if m%2 == 1
    then return 1

  if aySitu[m].vol == cnd
    then return 1

  half = low(m/2)
  if aySitu[m] initiated 
    then  if cnd <= half
            then  return (int)anySitu[m].pSCond[cnd].v
            else  return 0
    
  aySitu[m].vol = m

  for c <- 1 to half     //condition
    do h <- 0  
       rear(aySitu[m].pSCond) <- create SCond
      
       for d <- 1 to c
         do h <- h + SOLVE(m-d,d)

       if h==c
         then  aySitu[m].pSCond[c].v = flase 
         else  aySitu[m].pSCond[c].v = true;
       aySitu[m].pSCond[c].cond = c
               
  return (int)aySitu[m].pSCond[m].v

        算法SOLVE_OPT在原算法SOLVE的基础上作了以下改进:将SOVLE的中的m除2并向下取整,所得值赋给变量half;原第5行的控制逻辑,被改写,当传入的条件值cnd小于等于half时,仍由原来逻辑控制,当cnd大于half时,意味着取球数将会超过当前局面球数的一半,故必无解;原第11行中的m-1用half变量取代,从而使得每个局面的PScond链表的结点数也大大减少;SOLVE_OP新增的第1、2行主要是针对局面值是奇数的情况,在此情况下,当前选择方取球数只要小于局面值的1/2,就保证能取到最后一个球,故必有解。

        假设不考虑局面条件的限制,SOLVE_OPT按递归公式A可以展开为:

        

        

        

        
        

        ......

        

       假设,则有

       那么 

                                                             

                                                            


     也就是说当  时,成立。


     算法SOLVE_OPT,可以接受。


设计这样一个游戏,我们可以创建一个名为"BashGame"的小程序,它将包含以下几个部分: 1. 游戏类(BashGame):定义游戏状态、规则以及回合处理。我们将维护一个剩余数变量,初始化为20,并设置一个标志来判断是否轮到用户还是电脑。 ```python class BashGame: def __init__(self, balls=20): self.balls = balls self.turn = "user" def take_ball(self, quantity): if self.balls >= quantity: self.balls -= quantity # 更新回合 self.turn = "computer" if self.turn == "user" else "user" else: print("不够了,无法操作") def double_take(self): self.take_ball(2) def restart_game(self): self.balls = 20 self.turn = "user" ``` 2. UI 界面(Tkinter):使用 Tkinter 创建一个简单窗口,包括按钮用于择操作(取一个、取两个、重新开始),并显示当前的数量。 ```python import tkinter as tk def handle_action(): action = button.get() game_func = getattr(game, action) game_func() # 初始化界面 root = tk.Tk() game = BashGame() frame = tk.Frame(root) frame.pack() button_var = tk.StringVar() button_one = tk.Radiobutton(frame, text="取一个", variable=button_var, value="take_ball") button_two = tk.Radiobutton(frame, text="取两个", variable=button_var, value="double_take") button_reset = tk.Button(frame, text="重新开始", command=lambda: handle_action()) button_one.grid(row=0, column=0) button_two.grid(row=0, column=1) button_reset.grid(row=0, column=2) # 设置初始界面 button_var.set("取一个") tk.mainloop() ``` 在这个游戏中,计算机始终会在用户取后立即取走剩余的一个,无论用户怎么,最终都会剩下7个给用户,因此保证了计算机的胜利。为了增加颜色多样性,你可以通过修改按钮样式、背景颜色等来装饰UI。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值