【BFS】CODE[VS] 1226 倒水问题 (BFS+模拟)

本文通过广度优先搜索(BFS)解决了一个经典的倒水问题,代码中使用了结构体来表示状态,并借助队列实现了状态的遍历。讨论了在不同条件下水壶间转移水的具体操作。

点击被抓去倒水


这道题主要考察代码能力
模拟倒水的过程,结果因为码力太弱,漏了两种情况(x和y全倒入一个(x或y)不满)
然后就没有然后了

最近超喜欢压代码怎么破???


代码如下:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>

const int maxn = 333;

using namespace std;

int x,y,z;
bool vis[maxn][maxn];

struct state{
    int x,y,step;
};

state f;

queue<state>q;

int bfs()
{
    q.push(f);
    vis[f.x][f.y] = 1;
    while(q.size())
    {
        f = q.front();
        q.pop();
        if(f.x == z|| f.y == z) return f.step;//最近超喜欢压代码! 
        if(f.x < x && vis[x][f.y] == 0) { q.push((state){x,f.y,f.step+1}); vis[x][f.y] = 1;}//倒满x 
        if(f.y < y && vis[f.x][y] == 0) { q.push((state){f.x,y,f.step+1}); vis[f.x][y] = 1;}//倒满y 
        if(f.x && vis[0][f.y] == 0) { q.push((state){0,f.y,f.step+1}); vis[0][f.y] = 1;}//倒空x 
        if(f.y && vis[f.x][0] == 0) { q.push((state){f.x,0,f.step+1}); vis[f.x][0] = 1;}//倒空y 
        if(f.x >= y-f.y && vis[f.x-(y-f.y)][y] == 0){ q.push((state) {f.x-(y-f.y),y,f.step+1}); vis[f.x-(y-f.y)][y] = 1;}//从x倒入y中填满y 
        if(f.y >= x-f.x && vis[x][f.y-(x-f.x)] == 0){ q.push((state) {x,f.y-(x-f.x),f.step+1}); vis[x][f.y-(x-f.x)] = 1;}//从y倒入x中填满x 
        if(f.x < y-f.y && vis[0][f.x+f.y] == 0) { q.push((state){0,f.x+f.y,f.step+1}); vis[0][f.x+f.y] = 1;}//全部x加入y    
        if(f.y < x-f.x && vis[f.x+f.y][0] == 0) { q.push((state){f.x+f.y,0,f.step+1}); vis[f.x+f.y][0] = 1;}//全部y加入x 
    }
    return -1; 
}


int main()
{
    scanf("%d%d%d",&x,&y,&z);
    int ans = bfs();
    if(ans != -1)
    {
        printf("%d\n",ans);
        return 0;   
    } 
    printf("impossible\n");
return 0;
}

THE END

By Peacefuldoge

http://blog.youkuaiyun.com/loi_peacefuldog

import tkinter as tk from tkinter import ttk, messagebox import copy from collections import deque import time class WaterSortGUI: def __init__(self, root): self.root = root self.root.title("Water Sort Puzzle Solver") self.root.geometry("900x700") self.root.resizable(True, True) # 确保中文正常显示 self.style = ttk.Style() self.style.configure("TLabel", font=("SimHei", 10)) self.style.configure("TButton", font=("SimHei", 10)) # 状态变量 self.initial_bottles = [] self.max_capacity = 4 self.solution = None self.current_step = 0 self.auto_play = False self.play_speed = 1.0 # 播放速度因子 # 创建界面组件 self.create_widgets() def create_widgets(self): # 顶部控制栏 control_frame = ttk.Frame(self.root) control_frame.pack(fill=tk.X, padx=10, pady=10) ttk.Label(control_frame, text="瓶子数量:").pack(side=tk.LEFT, padx=5) self.num_bottles_var = tk.StringVar(value="4") ttk.Entry(control_frame, textvariable=self.num_bottles_var, width=5).pack(side=tk.LEFT, padx=5) ttk.Label(control_frame, text="最大容量:").pack(side=tk.LEFT, padx=5) self.capacity_var = tk.StringVar(value="4") ttk.Entry(control_frame, textvariable=self.capacity_var, width=5).pack(side=tk.LEFT, padx=5) ttk.Button(control_frame, text="输入初始状态", command=self.input_initial_state).pack(side=tk.LEFT, padx=10) ttk.Button(control_frame, text="求解", command=self.solve_puzzle).pack(side=tk.LEFT, padx=10) self.auto_play_var = tk.BooleanVar(value=False) ttk.Checkbutton(control_frame, text="自动播放", variable=self.auto_play_var).pack(side=tk.LEFT, padx=10) ttk.Label(control_frame, text="播放速度:").pack(side=tk.LEFT, padx=5) self.speed_scale = ttk.Scale(control_frame, from_=0.2, to=2.0, orient=tk.HORIZONTAL, variable=self.play_speed, length=100) self.speed_scale.pack(side=tk.LEFT, padx=5) ttk.Button(control_frame, text="上一步", command=self.prev_step).pack(side=tk.LEFT, padx=10) ttk.Button(control_frame, text="下一步", command=self.next_step).pack(side=tk.LEFT, padx=10) # 状态显示区 self.status_frame = ttk.Frame(self.root) self.status_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10) ttk.Label(self.status_frame, text="状态:").pack(anchor=tk.W) self.status_text = tk.Text(self.status_frame, height=5, wrap=tk.WORD) self.status_text.pack(fill=tk.X, padx=5, pady=5) self.status_text.config(state=tk.DISABLED) # 瓶子可视化区 self.bottles_frame = ttk.Frame(self.root) self.bottles_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10) # 解决方案区 solution_frame = ttk.Frame(self.root) solution_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10) ttk.Label(solution_frame, text="解决方案:").pack(anchor=tk.W) self.solution_text = tk.Text(solution_frame, height=10, wrap=tk.WORD) self.solution_text.pack(fill=tk.BOTH, expand=True, padx=5, pady=5) self.solution_text.config(state=tk.DISABLED) def input_initial_state(self): """获取用户输入的初始状态""" try: num_bottles = int(self.num_bottles_var.get()) self.max_capacity = int(self.capacity_var.get()) if num_bottles <= 0 or self.max_capacity <= 0: messagebox.showerror("错误", "瓶子数量和容量必须为正整数") return input_window = tk.Toplevel(self.root) input_window.title("输入初始状态") input_window.geometry(f"{400 + num_bottles * 100}x300") bottles_frame = ttk.Frame(input_window) bottles_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10) entry_widgets = [] for i in range(num_bottles): ttk.Label(bottles_frame, text=f"瓶子 {i+1}:").grid(row=i, column=0, padx=5, pady=5, sticky=tk.W) entry = ttk.Entry(bottles_frame, width=20) entry.grid(row=i, column=1, padx=5, pady=5) entry_widgets.append(entry) def confirm_input(): self.initial_bottles = [] for i in range(num_bottles): colors = entry_widgets[i].get().strip().split() if len(colors) > self.max_capacity: messagebox.showerror("错误", f"瓶子 {i+1} 的颜色数量超过容量") return self.initial_bottles.append(colors) self.update_bottles_display() self.status_text.config(state=tk.NORMAL) self.status_text.delete(1.0, tk.END) self.status_text.insert(tk.END, f"初始状态: {self.initial_bottles}") self.status_text.config(state=tk.DISABLED) input_window.destroy() ttk.Button(input_window, text="确认", command=confirm_input).pack(pady=10) except ValueError: messagebox.showerror("错误", "请输入有效的数字") def update_bottles_display(self): """更新瓶子可视化显示""" # 清除现有瓶子 for widget in self.bottles_frame.winfo_children(): widget.destroy() if not self.initial_bottles: ttk.Label(self.bottles_frame, text="请先输入初始状态").pack() return # 计算瓶子宽度和间距 num_bottles = len(self.initial_bottles) max_width = self.root.winfo_width() - 100 bottle_width = max(80, max_width // num_bottles - 20) for i, bottle in enumerate(self.initial_bottles): bottle_frame = ttk.Frame(self.bottles_frame, width=bottle_width, height=300) bottle_frame.pack(side=tk.LEFT, padx=10, pady=10, fill=tk.BOTH) # 绘制瓶子轮廓 bottle_canvas = tk.Canvas(bottle_frame, bg="white", width=bottle_width, height=300) bottle_canvas.pack(fill=tk.BOTH, expand=True) # 瓶子主体 bottle_body = bottle_canvas.create_rectangle( 10, 50, bottle_width-10, 250, outline="black", width=2 ) # 瓶口 bottle_neck = bottle_canvas.create_rectangle( bottle_width//2 - 10, 30, bottle_width//2 + 10, 50, outline="black", width=2, fill="gray" ) # 绘制颜色层 color_height = 200 / self.max_capacity # 每层颜色高度 for j, color in enumerate(bottle): if j >= self.max_capacity: break y = 250 - (j + 1) * color_height color = self.get_color_code(color) bottle_canvas.create_rectangle( 15, y, bottle_width-15, 250 - j * color_height, fill=color, outline="" ) # 瓶子编号 bottle_canvas.create_text( bottle_width//2, 270, text=f"瓶子 {i+1}" ) def get_color_code(self, color): """将颜色字符串转换为RGB颜色码""" color_map = { 'R': 'red', 'G': 'green', 'B': 'blue', 'Y': 'yellow', 'O': 'orange', 'P': 'purple', 'W': 'white', 'Bk': 'black', 'C': 'cyan' } return color_map.get(color, 'gray') def solve_puzzle(self): """求解问题""" if not self.initial_bottles: messagebox.showinfo("提示", "请先输入初始状态") return try: self.status_text.config(state=tk.NORMAL) self.status_text.delete(1.0, tk.END) self.status_text.insert(tk.END, "正在求解...") self.status_text.config(state=tk.DISABLED) self.root.update() # 调用原有算法求解 self.solution = solve_water_sort(self.initial_bottles, self.max_capacity) if not self.solution: self.status_text.config(state=tk.NORMAL) self.status_text.delete(1.0, tk.END) self.status_text.insert(tk.END, "无解") self.status_text.config(state=tk.DISABLED) messagebox.showinfo("结果", "无解") return # 显示解决方案 self.solution_text.config(state=tk.NORMAL) self.solution_text.delete(1.0, tk.END) self.solution_text.insert(tk.END, f"共需要 {len(self.solution)-1} 步\n\n") for i, state in enumerate(self.solution): self.solution_text.insert(tk.END, f"步骤 {i}:\n") for j, bottle in enumerate(state): self.solution_text.insert(tk.END, f"瓶子 {j+1}: {bottle}\n") self.solution_text.insert(tk.END, "\n") self.solution_text.config(state=tk.DISABLED) self.status_text.config(state=tk.NORMAL) self.status_text.delete(1.0, tk.END) self.status_text.insert(tk.END, f"已找到解决方案,共 {len(self.solution)-1} 步") self.status_text.config(state=tk.DISABLED) self.current_step = 0 self.update_bottles_display_from_solution() if self.auto_play_var.get(): self.auto_play_solution() except Exception as e: messagebox.showerror("错误", f"求解过程中发生错误: {str(e)}") self.status_text.config(state=tk.NORMAL) self.status_text.delete(1.0, tk.END) self.status_text.insert(tk.END, f"错误: {str(e)}") self.status_text.config(state=tk.DISABLED) def update_bottles_display_from_solution(self): """根据解决方案更新瓶子显示""" if not self.solution or self.current_step >= len(self.solution): return state = self.solution[self.current_step] self.initial_bottles = [copy.deepcopy(b) for b in state] self.update_bottles_display() self.status_text.config(state=tk.NORMAL) self.status_text.delete(1.0, tk.END) self.status_text.insert(tk.END, f"当前步骤: {self.current_step}/{len(self.solution)-1}") self.status_text.config(state=tk.DISABLED) def prev_step(self): """上一步""" if not self.solution or self.current_step <= 0: return self.current_step -= 1 self.update_bottles_display_from_solution() def next_step(self): """下一步""" if not self.solution or self.current_step >= len(self.solution) - 1: return self.current_step += 1 self.update_bottles_display_from_solution() if self.auto_play_var.get() and self.current_step < len(self.solution) - 1: self.root.after(int(500 * self.play_speed), self.next_step) def auto_play_solution(self): """自动播放解决方案""" if not self.auto_play_var.get() or self.current_step >= len(self.solution) - 1: return self.current_step += 1 self.update_bottles_display_from_solution() if self.current_step < len(self.solution) - 1: self.root.after(int(500 * self.play_speed), self.auto_play_solution) def is_goal_state(bottles): """检查是否达到目标状态:每个瓶子只有一种颜色或为空""" for bottle in bottles: if len(set(bottle)) > 1: return False return True def is_valid_pour(source, target, max_capacity=4): """检查是否可以从source瓶倒入target瓶""" if not source: # 源瓶为空 return False if not target: # 目标瓶为空 - 可以倒入 return True if len(target) >= max_capacity: # 目标瓶已满 return False return source[-1] == target[-1] # 颜色相同才能倒入 def pour_water(source_bottle, target_bottle, max_capacity=4): """执行倒水操作,返回新的源瓶和目标瓶状态""" source = copy.deepcopy(source_bottle) target = copy.deepcopy(target_bottle) while is_valid_pour(source, target, max_capacity) and len(target) < max_capacity: target.append(source.pop()) return source, target def bottle_hash(bottles): """为瓶子状态创建唯一哈希值""" return tuple(tuple(bottle) for bottle in sorted(bottles)) def solve_water_sort(initial_bottles, max_capacity=4): """解决颜色分类倒水问题的主函数,支持自定义瓶子最大容量""" queue = deque() visited = set() parent = {} initial_state = [list(bottle) for bottle in initial_bottles] queue.append(initial_state) visited.add(bottle_hash(initial_state)) parent[bottle_hash(initial_state)] = None while queue: current_state = queue.popleft() if is_goal_state(current_state): path = [] state = current_state while state is not None: path.append(state) state = parent.get(bottle_hash(state), None) return path[::-1] # 反转路径,从初始到目标 for i in range(len(current_state)): for j in range(len(current_state)): if i == j: continue if is_valid_pour(current_state[i], current_state[j], max_capacity): new_state = copy.deepcopy(current_state) new_source, new_target = pour_water(new_state[i], new_state[j], max_capacity) new_state[i] = new_source new_state[j] = new_target state_hash = bottle_hash(new_state) if state_hash not in visited: visited.add(state_hash) parent[state_hash] = current_state queue.append(new_state) return None # 主程序入口 if __name__ == "__main__": root = tk.Tk() app = WaterSortGUI(root) root.mainloop()给上述代码画一个软件流程图
最新发布
07-07
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值