gym/101741D. Elevator

本文介绍了一种动态规划问题的解决思路,通过性质观察和数据结构优化将时间复杂度从O(n^2)降低到更高效的级别。针对特定问题,文章详细解释了如何利用单调性和线段树来优化状态转移方程。

https://codeforces.com/gym/101741/problem/D

首先有简单的dp,dp[i]=min{max{dp[j-1],t[i]}+2*max{a[j]--a[i]}} ,然后发现这个怎么都要n^2,好像没撒能维护的数据结构

然后要观察出一个性质,就是后面如果有比a[i]大的,当前这个一定跟后面那个更大的一起走,这个性质其实看下面化简了的dp式子也能看出来,这个性质有点像18桂林的Ahttps://blog.youkuaiyun.com/liufengwei1/article/details/109756288

然后我们合并一下,使得a[i]严格递减,dp就变成了dp[i]=min{max{dp[j-1],t[i]},2*a[j]}

那么对j二分一下,dp[j-1]<=t[i]的,dp[i]=t[i]+2*a[j],否则dp[i]=dp[j-1]+2*a[j],前面那个由于是a递减的,所以最小的a[j]就是边界上的,右边这个用线段树维护一下就行了

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
 
const int maxl=3e5+10;
const ll inf=1ll<<60;
 
int n,m,cnt,tot;ll ans;
int ctin[maxl],ca[maxl],b[maxl],sufmx[maxl];
ll tin[maxl],a[maxl],dp[maxl];
struct node
{
	int l,r;
	ll mi;
}tr[maxl*4];
 
inline void build(int k,int l,int r)
{
	tr[k].l=l;tr[k].r=r;tr[k].mi=0;
	if(l==r)
		return;
	int mid=(l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
}
 
inline void prework()
{
	for(int i=1;i<=n;i++)
		scanf("%d%d",&ctin[i],&ca[i]);
	sufmx[n]=ca[n];
	for(int i=n-1;i>=1;i--)
		sufmx[i]=max(sufmx[i+1],ca[i]);
	cnt=0;sufmx[n+1]=0;
	for(int i=1;i<=n;i++)
	{
		if(sufmx[i+1]>=ca[i])
			continue;
		b[++cnt]=i;
		tin[cnt]=ctin[i];a[cnt]=ca[i];
	}
	n=cnt;
	build(1,1,n);
}
 
inline void upd(int k,int l,ll x)
{
	if(tr[k].l==tr[k].r)
	{
		tr[k].mi=x;
		return;
	}
	int mid=(tr[k].l+tr[k].r)>>1;
	if(l<=mid)
		upd(k<<1,l,x);
	else
		upd(k<<1|1,l,x);
	tr[k].mi=min(tr[k<<1].mi,tr[k<<1|1].mi);
}
 
inline ll getmi(int k,int l,int r)
{
	if(tr[k].l==l && tr[k].r==r)
		return tr[k].mi;
	int mid=(tr[k].l+tr[k].r)>>1;
	if(r<=mid)
		return getmi(k<<1,l,r);
	else if(l>mid)
		return getmi(k<<1|1,l,r);
	else
		return min(getmi(k<<1,l,mid),getmi(k<<1|1,mid+1,r));
}
 
inline void mainwork()
{
	for(int i=1;i<=n;i++)
	{
		upd(1,i,dp[i-1]+2*a[i]);
		if(dp[i-1]<=tin[i])
			dp[i]=tin[i]+2*a[i];
		else
		{
			int l=0;
			for(int j=20;j>=0;j--)
			if(l+(1<<j)<=i-1 && dp[l+(1<<j)]<=tin[i])
				l+=(1<<j);
			dp[i]=tin[i]+2*a[l+1];
			dp[i]=min(dp[i],getmi(1,l+2,i));
		}
	}
}
 
inline void print()
{
	printf("%lld\n",dp[n]);
}
 
int main()
{
	while(~scanf("%d",&n))
	{
		prework();
		mainwork();
		print();
	}
	return 0;
}

 

from abc import ABC import numpy as np import airsim import gym # from tasks import Shaping from jsbsim_simulator import Simulation from jsbsim_aircraft import Aircraft, cessna172P, ball, x8 from debug_utils import * import jsbsim_properties as prp from simple_pid import PID from autopilot import X8Autopilot from navigation import WindEstimation from report_diagrams import ReportGraphs from image_processing import AirSimImages, SemanticImageSegmentation from typing import Type, Tuple, Dict class ClosedLoop: """ A class to run airsim, JSBSim and join the other classes together ... Attributes: ---------- sim_time : float how many seconds to run the simulation for display_graphics : bool decides whether to run the airsim graphic update in unreal, required for image_processing input airspeed : float fixed airspeed used to fly the aircraft if airspeed_hold_w_throttle a/p used agent_interaction_frequency_hz : float how often the agent selects a new action, should be equal to or the lowest frequency airsim_frequency_hz : float how often to update the airsim graphic simulation sim_frequency_hz : float how often to update the JSBSim input, should not be less than 120Hz to avoid unexpected behaviour aircraft : Aircraft the aircraft type used, x8 by default, changing this will likely require a change in the autopilot used init_conditions : Dict[prp.Property, float] = None the simulations initial conditions None by default as in basic_ic.xml debug_level : int the level of debugging sent to the terminal by JSBSim - 0 is limited - 1 is core values - 2 gives all calls within the C++ source code Methods: ------ simulation_loop(profile : tuple(tuple)) updates airsim and JSBSim in the loop get_graph_data() gets the information required to produce debug type graphics generate_figures() produce required graphics """ def __init__(self, sim_time: float, display_graphics: bool = True, airspeed: float = 30.0, agent_interaction_frequency: float = 12.0, airsim_frequency_hz: float = 392.0, sim_frequency_hz: float = 240.0, aircraft: Aircraft = x8, init_conditions: bool = None, debug_level: int = 0): self.sim_time = sim_time self.display_graphics = display_graphics self.airspeed = airspeed self.aircraft = aircraft self.sim: Simulation = Simulation(sim_frequency_hz, aircraft, init_conditions, debug_level) self.agent_interaction_frequency = agent_interaction_frequency self.sim_frequency_hz = sim_frequency_hz self.airsim_frequency_hz = airsim_frequency_hz self.ap: X8Autopilot = X8Autopilot(self.sim) self.graph: DebugGraphs = DebugGraphs(self.sim) self.report: ReportGraphs = ReportGraphs(self.sim) self.debug_aero: DebugFDM = DebugFDM(self.sim) self.wind_estimate: WindEstimation = WindEstimation(self.sim) self.over: bool = False def simulation_loop(self, profile: tuple) -> None: """ Runs the closed loop simulation and updates to airsim simulation based on the class level definitions :param profile: a tuple of tuples of the aircraft's profile in (lat [m], long [m], alt [feet]) :return: None """ update_num = int(self.sim_time * self.sim_frequency_hz) # how many simulation steps to update the simulation relative_update = self.airsim_frequency_hz / self.sim_frequency_hz # rate between airsim and JSBSim graphic_update = 0 image = AirSimImages(self.sim) image.get_np_image(image_type=airsim.ImageType.Scene) for i in range(update_num): graphic_i = relative_update * i graphic_update_old = graphic_update graphic_update = graphic_i // 1.0 # print(graphic_i, graphic_update_old, graphic_update) # print(self.display_graphics) if self.display_graphics and graphic_update > graphic_update_old: self.sim.update_airsim() # print('update_airsim') self.ap.airspeed_hold_w_throttle(self.airspeed) self.get_graph_data() if not self.over: self.over = self.ap.arc_path(profile, 400) if self.over: print('over and out!') break self.sim.run() def test_loop(self) -> None: """ A loop to test the aircraft's flight dynamic model :return: None """ update_num = int(self.sim_time * self.sim_frequency_hz) # how many simulation steps to update the simulation relative_update = self.airsim_frequency_hz / self.sim_frequency_hz # rate between airsim and JSBSim graphic_update = 0 for i in range(update_num): graphic_i = relative_update * i graphic_update_old = graphic_update graphic_update = graphic_i // 1.0 # print(graphic_i, graphic_update_old, graphic_update) # print(self.display_graphics) if self.display_graphics and graphic_update > graphic_update_old: self.sim.update_airsim() # print('update_airsim') # elevator = 0.0 # aileron = 0.0 # tla = 0.0 # self.ap.test_controls(elevator, aileron, tla) # self.ap.altitude_hold(1000) # self.ap.heading_hold(0) # self.ap.roll_hold(5 * math.pi / 180) # self.ap.pitch_hold(5.0 * math.pi / 180.0) if self.sim[prp.sim_time_s] >= 5.0: # self.ap.heading_hold(120.0) # self.ap.roll_hold(0.0 * math.pi / 180.0) self.ap.airspeed_hold_w_throttle(self.airspeed) # self.ap.pitch_hold(10.0 * (math.pi / 180.0)) self.ap.altitude_hold(800) self.get_graph_data() self.sim.run() def get_graph_data(self) -> None: """ Gets the information required to produce debug type graphics :return: """ self.graph.get_abs_pos_data() self.graph.get_airspeed() self.graph.get_alpha() self.graph.get_control_data() self.graph.get_time_data() self.graph.get_pos_data() self.graph.get_angle_data() self.graph.get_rate_data() self.report.get_graph_info() def generate_figures(self) -> None: """ Produce required graphics, outputs them in the desired graphic environment :return: None """ self.graph.control_plot() self.graph.trace_plot_abs() self.graph.three_d_scene() self.graph.pitch_rate_plot() self.graph.roll_rate_plot() # self.graph.roll_rate_plot() # self.debug_aero.get_pitch_values() def run_simulator() -> None: """ Runs the JSBSim and Airsim in the loop when executed as a script :return: None """ env = ClosedLoop(750, True) circuit_profile = ((0, 0, 1000), (4000, 0, 1000), (4000, 4000, 1000), (0, 4000, 1000), (0, 0, 20), (4000, 0, 20), (4000, 4000, 20)) ice_profile = ((0, 0, 0), (1200, 0, 0), (1300, 150, 0), (540, 530, -80), (0, 0, -150), (100, 100, -100)) square = ((0, 0, 0), (2000, 0, 0), (2000, 2000, 0), (0, 2000, 0), (0, 0, 0), (2000, 0, 0), (2000, 2000, 0)) approach = ((0, 0, 0), (2000, 0, 800), (2000, 2000, 600), (0, 2000, 400), (0, 0, 200), (2000, 0, 100), (2000, 2000, 100), (0, 2000, 100), (0, 0, 100)) rectangle = ((0, 0, 0), (2000, 0, 1000), (2000, 2000, 500), (-2000, 2000, 300), (-2000, 0, 100), (2000, 0, 20), (2000, 2000, 20), (-2000, 2000, 20)) env.simulation_loop(rectangle) env.generate_figures() env.report.trace_plot(rectangle) env.report.control_response(0, 750, 240) env.report.three_d_plot(300, 750, 240) print('Simulation ended') def run_simulator_test() -> None: """ Runs JSBSim in the test loop when executed as a script to test the FDM :return: None """ sim_frequency = 240 env = ClosedLoop(65.0, True, 30, 12, 24, sim_frequency) env.test_loop() env.generate_figures() print('Simulation ended') if __name__ == '__main__': run_simulator() # run_simulator_test()分析这个代码,我需要使得无人机按照我的初始姿态和位置向下俯冲,如何修改代码,可以先提供一个初始高度在300米,向下俯冲到地面,中间需要经过我给出的点(1.003, -0.737, -87.545) (2.006, -1.474, -82.703) (3.009, -2.211, -77.86) (4.012, -2.948, -73.018) (5.015, -3.685, -68.175) (6.017, -4.422, -63.332) (7.02, -5.16, -58.49) (8.023, -5.897, -53.647) (9.026, -6.634, -48.805) (10.029, -7.371, -43.962) (11.032, -8.108, -39.119) (12.035, -8.845, -34.277) (13.038, -9.582, -29.434) (14.041, -10.32, -24.592) (15.044, -11.057, -19.749) (16.047, -11.794, -14.906) (17.05, -12.531, -10.064) (18.053, -13.268, -5.221) (19.056, -14.005, -0.379)的在第一个点的俯仰角度是向下70度偏转角你自己给定的示例完整代码,不需要考虑安全,并且告诉我其他需要修改的代码位置和修改方案,最终完成俯冲,并且经过所有点
06-07
<think>好的,我现在需要解决用户遇到的AssertionError,错误信息是“environment must inherit from gym.Env class”。用户提到他们使用的是OpenAI Gym,所以这应该和自定义环境有关。首先,我得回想一下Gym库中创建环境的基本要求。 根据引用[2]和[3],Gym的环境必须指定动作空间(action space)和观察空间(observation space)。此外,用户的问题特别提到环境未继承自gym.Env类,这说明他们可能在自定义环境时没有正确继承基类。正确的做法是让自定义环境类继承gym.Env,并在__init__方法中定义action_space和observation_space。 接下来,我需要检查用户可能的代码结构。用户可能在定义自己的环境时没有正确继承,比如可能漏掉了super().__init__()的调用,或者没有正确初始化父类。例如,正确的类定义应该是class MyEnv(gym.Env):,然后在__init__中调用super().__init__(),并定义action_space和observation_space。 另外,引用[4]提到版本兼容性问题,比如Gym 0.18.0可能需要特定版本的Python或其他依赖库。但用户当前的错误更可能与代码结构有关,而不是版本问题,除非他们的Gym版本过旧导致基类路径变化。不过根据引用[2],Gym的文档明确指出环境必须指定action space,所以继承自gym.Env是必须的步骤。 可能的解决方案包括:确保自定义环境类正确继承gym.Env,并在初始化时定义必要的空间。例如,在__init__方法中,使用self.action_space = gym.spaces.Discrete(2)这样的语句来定义动作空间,观察空间同理。同时,必须实现_env的step、reset、render等方法,尤其是reset需要返回正确的观察值,否则可能引发如引用[1]中的错误,即返回类型不正确。 此外,用户可能在实例化环境时没有正确注册或创建环境实例,比如应该通过gym.make()注册后再使用,或者直接实例化自定义类。如果直接实例化,需要确保所有父类方法都被正确覆盖。 还需要检查Gym的版本是否过时或存在已知问题,如引用[2]提到的安装问题,可能需要降级pip或手动修复依赖。但用户当前的问题更可能是代码结构问题,而非安装问题,除非他们的Gym版本确实存在继承方面的bug。 总结,解决步骤应该是:1. 确保自定义环境继承gym.Env;2. 在__init__中初始化action和observation空间;3. 实现必要的方法如reset和step;4. 检查Gym版本和依赖是否正确安装。</think>### 解决AssertionError: "environment must inherit from gym.Env class" 此错误表明自定义环境未正确继承Gym库的基类`gym.Env`。以下是具体解决步骤: --- #### 1. **确保环境类继承自`gym.Env`** 自定义环境类必须显式继承`gym.Env`,并在`__init__`方法中调用父类初始化: ```python import gym from gym import spaces class CustomEnv(gym.Env): def __init__(self): super(CustomEnv, self).__init__() # 必须调用父类初始化[^3] self.action_space = spaces.Discrete(2) # 定义动作空间 self.observation_space = spaces.Box(low=0, high=1, shape=(4,)) # 定义观测空间 ``` --- #### 2. **定义必需方法** 必须实现`reset()`和`step()`方法,且`reset()`需返回**观测值+信息字典**(即使为空): ```python def reset(self): observation = self._get_observation() # 自定义观测值获取逻辑 return observation, {} # 返回元组(观测值,信息字典)[^1] def step(self, action): # 实现环境交互逻辑 return observation, reward, done, False, {} ``` --- #### 3. **验证环境注册与调用** 若通过`gym.make()`调用环境,需先注册: ```python from gym.envs.registration import register register(id="CustomEnv-v0", entry_point="your_module:CustomEnv") env = gym.make("CustomEnv-v0") ``` --- #### 4. **检查Gym版本兼容性** 若使用旧版Gym(如0.18.0),需确保依赖兼容: - 降级`pip`至20.3.4: ```bash pip install pip==20.3.4 ``` - 手动修复依赖后安装Gym(参考引用[2][^2]): ```bash sed -i 's/opencv-python>=3./opencv-python>=3.0/' setup.py pip install . ``` --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值