取水问题——python代码

from email import message
import tkinter
from turtle import reset
import numpy as np
import matplotlib.pyplot as plt
import tkinter.messagebox
from tkinter import *
from PIL import Image, ImageTk


plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = ['SimHei']

#存储已访问的节点 
class State:
    def __init__(self,a,b,prev,step,operation):
        self.a=a   #A现有水的升数
        self.b=b   #B现有水的升数
        self.prev=prev   #父节点指针
        self.step=step   #节点数,也就是记录步数
        self.operation=operation
      
visited=[[False for i in range(1000)]for j in range(1000)]

#广度优先算法(BFS)
def BFS(capativy_a,capativy_b,left_c,order):
    queue=[]
    
    s=State(a=0,b=0,prev=None,step=0,operation=None)
    queue.append(s)
    visited[0][0]=True

    while queue:
        state=queue.pop(0)
        for i in range(6):
            a ,b ,operation =None,None,None
            if i==0:
                operation = "将杯子A的水倒空"
                a=0
                b=state.b
            elif i==1:
                operation = "将杯子B的水倒空"
                a=state.a
                b=0
            elif i==2:
                operation = "将杯子A的水倒满"
                a=capativy_a
                b=state.b
            elif i==3:
                operation = "将杯子B的水倒满"
                b=capativy_b
                a=state.a
            elif i==4:#将杯子A的水倒入杯子B中
                if capativy_b-state.b>state.a:
                    operation = "将杯子A的水倒入杯子B,直至杯子A被倒空"
                    a=0
                    b=state.a+state.b
                else :
                    operation = "将杯子A的水倒入杯子B,直至杯子B被倒满"
                    b=capativy_b
                    a=state.a-(capativy_b-state.b)
            elif i==5:#将杯子B的水倒入杯子A中
                if capativy_a-state.a>state.b:
                    operation = "杯子B中的水倒入杯子A中,直至杯子B被倒空"
                    b=0
                    a=state.a+state.b
                else:
                    operation = "杯子B中的水倒入杯子A中,直至杯子A被倒满"
                    a=capativy_a
                    b=state.b-(capativy_a-state.a)
            if  not visited[a][b]:
                new_state=State(a=a,b=b,prev=state,step=state.step+1,operation=operation)
                visited[a][b]=True
                queue.append(new_state)
                #order_check(str(order))
                if order == 'a' or order == 'A':
                    if left_c==a:
                        return new_state
                elif order == 'b' or order == 'B':
                    if left_c==b:
                        return new_state
    return None

def get_path(state,x_axis,y_axis):
    path=[]
    queue_a=[]
    queue_b=[]
    
    while state.prev:
        queue_a.append(state.a)
        queue_b.append(state.b)
        path.append(state.operation)
        state = state.prev
    i=len(path)
    queue_a.append(0)
    queue_b.append(0)
    queue_a.reverse()
    queue_b.reverse()
    plot_map(queue_a,queue_b,x_axis,y_axis,i)
    return path[::-1]

#祖贝等式Ax+By=C
def gcd(A,B,C):
    if A > B:
        min = B
    else:
        min = A
    for i in range(1,min+1):
        #满足公因数的条件:
        if (A % i == 0) and (B % i == 0):
            c = i
    if C % c != 0:
        tkinter.messagebox.showerror(title="警告",message="问题无解")
        exit()

def order_check(order):
    if str(order) == 'a' or str(order) == 'A' or str(order) == 'b' or str(order) == 'B':
        return order
    else:
        tkinter.messagebox.showerror(title="警告",message="错误的数据格式")
        exit()

def plot_map(list_1,list_2,x_axis,y_axis,circle):
    x_ticks=range(x_axis)
    y_ticks=range(y_axis)
    plt.axis([0,x_axis,0,y_axis])
    plt.grid(True, linestyle="--", alpha=1)
    plt.title("取水问题的可视化"+"  "+"解决方案步数:"+str(circle))
    plt.xlabel("水杯A的容量")
    plt.ylabel("水杯B的容量")
    plt.xticks(x_ticks,fontsize=18)
    plt.yticks(y_ticks,fontsize=18)
    for i in range(0,circle):
        plt.annotate(i+1,xy=(list_1[i+1], list_2[i+1]),xytext=(list_1[i],list_2[i]),arrowprops=dict(facecolor='black', shrink=0.05),zorder=5)
    #plt.axis([0,x_axis,0,y_axis])
    plt.plot(list_1,list_2)
    plt.show()

def main():

    root = tkinter.Tk()
    root.title("取水问题 V1.0")
    root.minsize(600, 400)   #初始化窗口大小
    root.maxsize(1000,600)   #放大之后窗口大小

    labelt = tkinter.Label(root, text= "取水问题")
    labelt.place(relx = 0.4, rely = 0.10)

    labelt1 = tkinter.Label(root, text= "请确保您输入的数据满足以下要求:")
    labelt1.place(relx = 0.2, rely = 0.2)
    labelt2 = tkinter.Label(root, text= "1、两水杯容量应该互质;")
    labelt2.place(relx = 0.2, rely = 0.25)
    labelt3 = tkinter.Label(root, text= "2、两水杯容量的最大值应该大于想获得的升数。")
    labelt3.place(relx = 0.2, rely = 0.3)

    #创建输入框
    label1 = tkinter.Label(root, text= "请定义水杯A的容量(1-1000):")
    label1.place(relx = 0.12, rely = 0.4)   #relx距离左边框的距离, rely距离上边框的距离
    entry1 = tkinter.Entry(root)
    entry1.place(relx = 0.5, rely = 0.4, width = 200, height = 20)
    label2 = tkinter.Label(root, text= "请定义水杯B的容量(1-1000):")
    label2.place(relx = 0.12, rely = 0.5)
    entry2 = tkinter.Entry(root)
    entry2.place(relx = 0.5, rely = 0.5, width = 200, height = 20)
    label3 = tkinter.Label(root, text= "请输入想获得的升数:")
    label3.place(relx = 0.12, rely = 0.6)
    entry3 = tkinter.Entry(root)
    entry3.place(relx = 0.5, rely = 0.6, width = 200, height = 20)
    label4_1 = tkinter.Label(root, text= "你想在哪个水杯中获得所要求的水:")
    label4_1.place(relx = 0.12, rely = 0.7)
    label4_2 = tkinter.Label(root, text= "(A/B,大小写均可):")
    label4_2.place(relx = 0.12, rely = 0.75)
    entry4 = tkinter.Entry(root)
    entry4.place(relx = 0.5, rely = 0.7, width = 200, height = 20)

    #创建按钮
    button1 = tkinter.Button(root, text="计算")
    button1.place(relx = 0.38, rely = 0.8, width = 80)
    button2 = tkinter.Button(root, text="计算流程")
    button2.place(relx = 0.6, rely = 0.1, width = 80)

    label5 = tkinter.Label(root, text= "此版本每次成功计算后需要重新打开。")
    label5.place(relx = 0.3, rely = 0.9)

    def liuchen(self):
        global photo
        top = Toplevel()
        top.title("流程图")
        top.geometry("600x550")
        img = Image.open('E:\取水问题\流程图.png')
        photo = ImageTk.PhotoImage(img)
        label_img = tkinter.Label(top, image=photo)
        label_img.grid(row=1, column=0, pady=10)
        #img_png = Tkinter.PhotoImage(file = 'E:\倒水问题\流程图.png')
        #label_img = Tkinter.Label(root, image = img_png)
        #label_img.pack()

    def program(self):
        capativy_a = int(entry1.get()) #获取第一个输入框的值
        capativy_b = int(entry2.get()) #获取第二个输入框的值
        left_c = int(entry3.get()) #获取第三个输入框的值
        order = str(entry4.get()) #获取第四个输入框的值
        #首先判断数据格式是否正确,如果错误直接结束程序
        if capativy_a==0 or capativy_b==0 or left_c==0 or left_c>max(capativy_a,capativy_b) or capativy_a%capativy_b==0 or capativy_b%capativy_a==0:
            tkinter.messagebox.showerror(title="警告",message="错误的数据格式")    
        
        #判断所给数据是否有解,如果无解直接结束程序
        gcd(capativy_a,capativy_b,left_c)

        order_check(order)

        result = BFS(capativy_a,capativy_b,left_c,order)

        get_path(result,capativy_a,capativy_b)
    
    button1.bind("<ButtonRelease-1>",program) 
    button2.bind("<ButtonRelease-1>",liuchen)
    
    root.mainloop() 
    return

main()

这篇主要是代码,之后会上传相关的理论部分。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值