C - Monkey and Banana (动态规划)

本文介绍了一个有趣的编程问题——猴子搭塔。该问题涉及通过不同类型的砖块搭建尽可能高的塔,以帮助猴子拿到香蕉。文章提供了完整的代码实现及解析,探讨了如何通过动态规划算法解决这一问题。

点击打开链接


一组研究人员正在设计一项实验,以测试猴子的智商。他们将挂香蕉在建筑物的屋顶,同时,提供一些砖块给这些猴子。如果猴子足够聪明,它应当能够通过合理的放置一些砖块建立一个塔,并爬上去吃他们最喜欢的香蕉。
 
研究人员有n种类型的砖块,每种类型的砖块都有无限个。第i块砖块的长宽高分别用xi,yi,zi来表示。 同时,由于砖块是可以旋转的,每个砖块的3条边可以组成6种不同的长宽高。
 
在构建塔时,当且仅当A砖块的长和宽都分别小于B砖块的长和宽时,A砖块才能放到B砖块的上面,因为必须留有一些空间让猴子来踩。
 
你的任务是编写一个程序,计算猴子们最高可以堆出的砖块们的高度。
Input
输入文件包含多组测试数据。
每个测试用例的第一行包含一个整数n,代表不同种类的砖块数目。n<=30.
接下来n行,每行3个数,分别表示砖块的长宽高。
当n= 0的时候,无需输出任何答案,测试结束。
Output
对于每组测试数据,输出最大高度。格式:Case 第几组数据: maximum height = 最大高度
Sample Input
1
10 20 30 

6 8 10 
5 5 5 

1 1 1 
2 2 2 
3 3 3 
4 4 4 
5 5 5 
6 6 6 
7 7 7 

31 41 59 
26 53 58 
97 93 23 
84 62 64 
33 83 27 
Sample Output
Case 1: maximum height = 40
Case 2: maximum height = 21 
Case 3: maximum height = 28 
Case 4: maximum height = 342 

题解:首先要考虑到输入坐标的排列(六种),根据长和宽的大小做一个简单的排序,以dp[i]代表第i块的高度,用双重循环遍历所有存在的可能,并取出其中的最大值。


#include<cstdio>
#include<algorithm>
using namespace std;

struct tt
{
	int a,b,c;
}t[200];
int m=0;
void add(int x,int y,int z)
{
	t[m].a=x;t[m].b=y;t[m].c=z;m++;
	t[m].a=x;t[m].b=z;t[m].c=y;m++;
	t[m].a=y;t[m].b=x;t[m].c=z;m++;
	t[m].a=y;t[m].b=z;t[m].c=x;m++;
	t[m].a=z;t[m].b=y;t[m].c=x;m++;
	t[m].a=z;t[m].b=x;t[m].c=y;m++;
}
int dp[200];
bool cmp(tt a,tt b)
{
	if(a.a==b.a)
	return a.b>b.b;
	return a.a>b.a;
}

int main()
{
	int n;
	int Case=1;
	while(scanf("%d",&n)!=EOF&&n)
	{
		m=0;
		for(int i=0;i<n;i++)
		{
			int x,y,z;
			scanf("%d%d%d",&x,&y,&z);
			add(x,y,z);//要考虑到所有的组合形式 
		}
		sort(t,t+m,cmp);//排序后并不是以底面积的大小为依据(可以考虑以底面积排序) 
		int ans=0;
		for(int i=0;i<m;i++)
		{
			dp[i]=t[i].c;//第i块方砖的高度 
			for(int j=0;j<i;j++)//j<i即dp[i]以上的dp数组都已赋值,并在确定 
			{                   //第一块砖后 将所有的砖再遍历一遍 
				if(t[i].a<t[j].a&&t[i].b<t[j].b)
				dp[i]=max(dp[i],dp[j]+t[i].c);//初始高度加上以后放上的高度并与前一个dp[i]比较取最大值 
				ans=max(ans,dp[i]);//将得到的答案与之前的比较取最大值 
			}
			
		}
		printf("Case %d: maximum height = %d\n",Case++,ans);
	}
return 0;
}






# 代码概述 该请求基于“猴子香蕉”问题,要求将符号逻辑规划问题转化为可执行的 Python 程序。程序需模拟猴子通过行走、推箱、爬箱、摘香蕉等动作,从初始状态达到目标状态。 我们将使用类和谓词函数来建模环境状态与动作,确保每一步操作都满足先决条件,并更新全局状态。 --- # 代码解析 ```python class MonkeyBananaProblem: def __init__(self): # 初始状态 self.monkey_at = 'a' self.box_at = 'c' self.banana_at = 'b' self.on_box = False self.has_banana = False def walk(self, pos): """猴子从当前位置走到指定位置""" if self.on_box: print("猴子正在箱子上,无法行走。") return False print(f"猴子从 {self.monkey_at} 走到 {pos}") self.monkey_at = pos return True def push_box(self, to_pos): """猴子将箱子从当前位置推到新位置""" if not (self.monkey_at == self.box_at and not self.on_box): print("猴子必须和箱子在同一位置且不在箱子上才能推箱子。") return False print(f"猴子将箱子从 {self.box_at} 推到 {to_pos}") self.box_at = to_pos self.monkey_at = to_pos return True def climb_up(self): """猴子爬上箱子""" if self.monkey_at != self.box_at: print("猴子必须在箱子旁边才能爬上箱子。") return False if self.on_box: print("猴子已经在箱子上了。") return False print("猴子爬上了箱子。") self.on_box = True return True def grasp_banana(self): """猴子香蕉""" if self.on_box and self.box_at == self.banana_at and self.monkey_at == self.banana_at: print("猴子成功摘到了香蕉!") self.has_banana = True return True else: print("无法摘香蕉:需站在位于香蕉下方的箱子上。") return False def is_goal(self): """检查是否达到目标状态""" return self.has_banana and self.on_box and self.box_at == 'b' and self.monkey_at == 'b' def show_state(self): """打印当前状态""" print(f"当前位置 -> 猴子: {self.monkey_at}, 箱子: {self.box_at}, " f"香蕉: {self.banana_at}, 在箱子上: {self.on_box}, 已摘香蕉: {self.has_banana}") # 执行行动计划 if __name__ == "__main__": problem = MonkeyBananaProblem() print("初始状态:") problem.show_state() print("\n开始行动:") problem.walk('c') # 步骤1:从 a 走到 c problem.push_box('b') # 步骤2:将箱子从 c 推到 b problem.climb_up() # 步骤3:爬上箱子 problem.grasp_banana() # 步骤4:摘香蕉 print("\n最终状态:") problem.show_state() if problem.is_goal(): print("✅ 成功达成目标状态!") else: print("❌ 未达成目标状态。") ``` --- # 知识点 - **状态建模与封装**:使用类封装状态与行为,实现清晰的状态管理和方法调用,符合面向对象设计原则。 - **条件控制与动作验证**:每个动作前检查先决条件,防止非法状态转移,增强程序健壮性。 - **状态转移模拟**:通过顺序执行合法动作,模拟智能体在环境中的规划路径,体现经典AI问题求解思路。 写python代码,并且可以可视化
最新发布
11-05
# 代码概述 该请求要求在原有“猴子香蕉”问题的 Python 实现基础上,增加**可视化功能**,直观展示猴子、箱子和香蕉的位置变化过程。我们将使用 `matplotlib` 动态绘制房间布局,并通过帧动画模拟每一步操作。 --- # 代码解析 ```python import matplotlib.pyplot as plt import matplotlib.patches as patches from time import sleep class MonkeyBananaProblem: def __init__(self): # 初始状态 self.monkey_at = 'a' self.box_at = 'c' self.banana_at = 'b' self.on_box = False self.has_banana = False self.position_map = {'a': 1, 'b': 2, 'c': 3} # 位置映射为横坐标 self.fig, self.ax = plt.subplots(1, 1, figsize=(8, 5)) plt.ion() # 开启交互模式 def draw(self): """绘制当前状态""" self.ax.clear() self.ax.set_xlim(0, 4) self.ax.set_ylim(0, 3) self.ax.set_aspect('equal') self.ax.axis('off') self.ax.set_title("猴子香蕉问题", fontsize=16) # 房间地面线 self.ax.plot([0.5, 3.5], [0.8, 0.8], color='black', linewidth=2) # 标注位置 a, b, c for pos_key, x in self.position_map.items(): self.ax.text(x, 0.6, pos_key, ha='center', fontsize=12) # 绘制香蕉在 b 上方) banana_x = self.position_map[self.banana_at] self.ax.plot(banana_x, 2.5, 'yo', markersize=12, label="香蕉") self.ax.plot([banana_x - 0.2, banana_x + 0.2], [2.5, 2.5], 'y-', linewidth=3) self.ax.text(banana_x, 2.7, "🍌", fontsize=16, ha='center') # 绘制箱子 box_x = self.position_map[self.box_at] box = patches.Rectangle((box_x - 0.3, 0.8), 0.6, 0.6, linewidth=2, edgecolor='brown', facecolor='orange') self.ax.add_patch(box) self.ax.text(box_x, 0.5, "箱子", ha='center', fontsize=10, color='orange') # 绘制猴子 monkey_y = 1.4 if self.on_box else 1.0 # 站在箱子上则更高 face_color = 'green' if self.has_banana else 'gray' self.ax.plot(self.position_map[self.monkey_at], monkey_y, 'o', markersize=16, color=face_color) self.ax.text(self.position_map[self.monkey_at], monkey_y + 0.3, "🐵", fontsize=14, ha='center') # 显示提示信息 status_text = f"状态: 箱子@{self.box_at}, " status_text += "已摘香蕉!" if self.has_banana else "未摘香蕉" self.ax.text(0.5, 2.9, status_text, fontsize=10, ha='left', bbox=dict(facecolor='lightgray')) self.fig.canvas.draw() self.fig.canvas.flush_events() sleep(1.5) # 暂停以便观察 def walk(self, pos): if pos not in ['a', 'b', 'c']: print("无效位置。") return False if self.on_box: print("猴子正在箱子上,无法行走。") return False print(f"🐒 猴子从 {self.monkey_at} 走到 {pos}") self.monkey_at = pos self.draw() return True def push_box(self, to_pos): if to_pos not in ['a', 'b', 'c']: print("无效位置。") return False if not (self.monkey_at == self.box_at and not self.on_box): print("❌ 猴子必须与箱子同位置且不在箱子上才能推箱子。") return False print(f"💪 猴子将箱子从 {self.box_at} 推到 {to_pos}") self.box_at = to_pos self.monkey_at = to_pos self.draw() return True def climb_up(self): if self.monkey_at != self.box_at: print("❌ 猴子必须在箱子旁边才能爬上箱子。") return False if self.on_box: print("❌ 猴子已经在箱子上了。") return False print("🪜 猴子爬上了箱子!") self.on_box = True self.draw() return True def grasp_banana(self): if self.on_box and self.box_at == self.banana_at and self.monkey_at == self.banana_at: print("🎉 猴子成功摘到了香蕉!") self.has_banana = True self.draw() return True else: print("❌ 无法摘香蕉:需站在位于香蕉下方的箱子上。") return False def is_goal(self): return self.has_banana and self.on_box and self.box_at == 'b' and self.monkey_at == 'b' def show_state(self): print(f"📍 当前状态 -> 猴子: {self.monkey_at}, 箱子: {self.box_at}, 香蕉: {self.banana_at}, " f"在箱上: {self.on_box}, 已摘: {self.has_banana}") # 主程序执行 if __name__ == "__main__": problem = MonkeyBananaProblem() print("🌱 初始状态:") problem.show_state() problem.draw() print("\n🚀 开始行动序列:") problem.walk('c') # 步骤1:从 a 走到 c problem.push_box('b') # 步骤2:推箱子到 b problem.climb_up() # 步骤3:爬上箱子 problem.grasp_banana() # 步骤4:摘香蕉 print("\n🏁 最终状态:") problem.show_state() if problem.is_goal(): print("✅ 成功达成目标状态!任务完成!") else: print("❌ 未能达成目标。") plt.ioff() plt.show() # 保持窗口显示直到关闭 ``` --- # 知识点 - **状态建模与封装**:使用类封装状态与行为,实现清晰的状态管理和方法调用,符合面向对象设计原则。 - **条件控制与动作验证**:每个动作前检查先决条件,防止非法状态转移,增强程序健壮性。 - **动态可视化技术**:利用 `matplotlib` 实现图形化模拟,通过实时刷新画面展示智能体环境交互过程,提升理解与调试能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值