GYM 101606 K.Knightsbridge Rises(最大流-Dinic)

解决m个重物利用n个吊车吊至楼上的问题,通过网络流算法构建模型,确保每个吊车仅使用一次,并找出可行方案。

Problem K

Knightsbridge Rises

Description

现在有m

个重量分别为Ti的物品需要吊到楼上,有n个吊车,第i个吊车的重量为Wi,可以吊起的重量为Li,重量为0表示该吊车可以无代价的先放置在楼上以吊起重物或其他吊车,问如果安排吊车可以把这m

个重物都吊到楼上,一个吊车只能用一次

Input

第一行一整数n

表示吊车数量,之后n行每行两个整数Li,Wi表示第i个吊车可吊起的重量和自身的重量,之后输入一整数m表示要吊起的重物数,最后m个整数Ti表示第i个重物的重量
(1≤n,m≤100,0≤Li,Wi≤106,1≤Ti≤106)

 

Output

如果存在合法方案则输出m

行,第j行一个吊车编号序列a1,...,ak表示a1吊车可以直接放置在楼上,且第ai个吊车可以吊起第ai+1个吊车,1≤i<k,且第ak个吊车可以吊起j重物,否则输出imposiible

Solution

网络流,n个吊车看作两排n个点,拆点保证每个吊车至多用一次,m个重物看作m个点,建图如下:

1.源点向所有自身重量为0的吊车连容量为1的边表示这些吊车可以无代价放置在楼上

2.每个吊车拆成的第一个点向第二个点连容量为1的边来限流

3.如果Li≥Wj,即第i个吊车可以吊起第j个吊车,则从第i个吊车拆成的第二个点向第j个吊车拆成的第一个点连容量为1的边

4.如果Li≥Tj,即第i个吊车可以吊起第j个重物,则从第i个吊车拆成的第二个点向第j个重物连容量为1的边5.每个重物向汇点连容量为1的边,用最大流是否为m来判断是否所有的重物都可以被吊起

在最大流解决了方案的存在性之后,对整张网络的前向弧构成的图dfs,只走流量流完的边,来找到第i个重物是通过哪些吊车依次吊起的

这里用到一个骚操作,就是用dfs找到最大流上的点。因为这题每条边容量都为1,所以如果走过了就一定为零。

不知道为什么dinic才能过,以后最大流都用Dinic算法了哼

<think>根据用户提供的代码片段,他们正在尝试使用类似"PongNoFrameskip-v4"这样的环境名称,但在新版的Gym中这些环境已经被移除。因此,需要将代码迁移到新版Gym的ALE环境。解决方案:1.将环境名称改为新的ALE命名方式,例如"ALE/Pong-v5"等。2.注意,新版ALE环境默认不包含帧跳过(frame skipping)和帧堆叠(frame stacking),需要手动添加这些包装器(wrappers)来模拟旧版行为。3.如果用户有自定义的AtariWrapper,可能需要调整以适应新版环境。具体修改建议如下:原代码:ifargs.env_name =="pong":env= gym.make("PongNoFrameskip-v4")elif args.env_name== "breakout":env =gym.make("BreakoutNoFrameskip-v4")else:env =gym.make("BoxingNoFrameskip-v4")env= AtariWrapper(env)修改为:#首先,将环境名称映射到新的ALE名称env_id= {"pong": "ALE/Pong-v5","breakout": "ALE/Breakout-v5","boxing": "ALE/Boxing-v5"#注意:原代码中else分支是Boxing,这里使用小写匹配}.get(args.env_name, "ALE/Pong-v5")#默认使用Pong#创建基础环境env= gym.make(env_id, render_mode="rgb_array")#如果需要渲染,指定render_mode#然后应用帧跳过和帧堆叠等包装器#假设原来的AtariWrapper实现了帧跳过、帧堆叠和预处理等功能,我们可以用Gym提供的标准包装器替代#如果没有,则可以使用以下标准包装器:#每4帧执行一次动作,并返回中间帧的最大值(这是Atari的常见设置)env =gym.wrappers.AtariPreprocessing(env, frame_skip=4, grayscale_obs=True, scale_obs=True)#如果需要帧堆叠,可以再添加FrameStack包装器,通常堆叠4帧env =gym.wrappers.FrameStack(env,num_stack=4)注意:如果用户原来的AtariWrapper有特殊处理,可能需要调整。这里假设使用Gym自带的AtariPreprocessing和FrameStack。另外,需要确保安装了必要的包:pip installale-pygym[atari,accept-rom-license]如果用户需要保持与旧版相同的预处理,可以查看AtariPreprocessing的文档:https://www.gymlibrary.dev/api/wrappers/#ataripreprocessing但是,请注意,AtariPreprocessing默认会将图像转换为灰度,并且缩放为84x84。如果用户原来的AtariWrapper有不同的处理,需要相应调整参数。如果用户不想改变预处理方式,也可以自己实现包装器,但建议使用官方提供的包装器以确保兼容性。最后,由于环境名称的改变,用户需要将args.env_name与新的环境名称映射好。这里我假设用户传入的args.env_name是字符串"pong"、"breakout"或"boxing"(小写),如果原代码中传入的是大写,则需要调整映射字典。如果用户的环境名称参数是其他值,需要根据实际情况修改映射。因此,修改后的代码示例: ```python#导入必要的包装器importgymfrom gym.wrappers importAtariPreprocessing, FrameStack#环境名称映射字典env_map= {"pong": "ALE/Pong-v5","breakout": "ALE/Breakout-v5","boxing": "ALE/Boxing-v5" }#获取新环境名称,如果args.env_name不在字典中,则使用默认(例如Pong)env_id= env_map.get(args.env_name,"ALE/Pong-v5") #创建环境env =gym.make(env_id,render_mode="rgb_array")#如果需要渲染,可以指定render_mode#应用预处理:帧跳过4,灰度化,缩放为84x84env =AtariPreprocessing(env, frame_skip=4, grayscale_obs=True, scale_obs=True)#帧堆叠4帧env =FrameStack(env, num_stack=4)#注意:如果用户需要其他预处理参数(如不进行缩放,或者不同的帧跳过等),可以调整AtariPreprocessing的参数```注意:在Gym0.26及以上版本中,创建环境时需要指定render_mode(如果需要渲染的话)。在训练时可能不需要渲染,但在测试或展示时可能需要。这里指定为"rgb_array"以便后续如果需要获取图像。另外,如果用户代码中原来有`env =AtariWrapper(env)`,那么现在应该移除,因为我们已经用标准包装器替代了。如果用户原来的AtariWrapper有其他功能(比如奖励裁剪、结束条件等),则需要额外添加相应的包装器。以上修改应该能解决环境名称不存在的问题,并确保环境具有与旧版类似的帧跳过和预处理功能。 §§相关问题§§1.如何在新版Gym中自定义Atari环境的帧跳过(frame skipping)参数? 2.使用FrameStack包装器时如何确保观测空间的正确维度? 3.如果不想使用灰度图像,如何设置AtariPreprocessing包装器? 4.如何在新版Atari环境中获取游戏状态(如剩余生命值)以进行生命结束条件判断? 5.在迁移旧版Atari代码时,如何处理新版Gym环境返回的info字典结构变化?</think>根据您提供的代码片段,您正在尝试使用旧版Atari环境名称(如`PongNoFrameskip-v4`),这些名称在Gym 0.26+版本中已被弃用。以下是完整的解决方案: ### 代码修复方案 ```python import gym from gym.wrappers import FrameSkip, FrameStack, ResizeObservation, GrayScaleObservation # 环境名称映射表(旧名称 → 新名称) ENV_MAP = { "pong": "ALE/Pong-v5", "breakout": "ALE/Breakout-v5", "boxing": "ALE/Boxing-v5" } # 获取新版环境名称 env_id = ENV_MAP.get(args.env_name, "ALE/Pong-v5") # 默认使用Pong # 创建基础环境 env = gym.make( env_id, render_mode="rgb_array", # 渲染模式 obs_type="rgb", # 观测类型(rgb/gray/ram) full_action_space=False # 使用简化动作空间 ) # 应用必要的包装器(模拟旧版行为) env = FrameSkip(env, skip=4) # 帧跳过(每4帧执行一次动作) env = ResizeObservation(env, (84, 84)) # 调整观测尺寸 env = GrayScaleObservation(env) # 灰度化 env = FrameStack(env, 4) # 帧堆叠(堆叠最后4帧) # 替换您原有的AtariWrapper # env = AtariWrapper(env) # 删除或修改此包装器 ``` ### 关键修改说明: 1. **环境名称映射**: - 使用新版ALE前缀环境(`ALE/GameName-v5`) - 创建映射表处理不同游戏名称 2. **帧跳过与堆叠**: - `FrameSkip`包装器实现动作重复 - `FrameStack`包装器实现帧堆叠 - 参数`skip=4`和`stack_size=4`模拟旧版`NoFrameskip`行为 3. **观测预处理**: - `ResizeObservation`调整观测尺寸 - `GrayScaleObservation`转换为灰度图像 - 替代您原有的`AtariWrapper` 4. **环境配置**: - `render_mode="rgb_array"` 获取图像数据 - `full_action_space=False` 使用简化动作空间(18个动作) - `obs_type="rgb"` 获取RGB图像观测 ### 依赖安装: ```bash pip install "gym[atari,accept-rom-license]" ale-py ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值