LintCode 253: Minimum Type Way (双序列DP好题)

253. Minimum Type Way

You are given a string only contains lower or upper English characters that you want to type.
At the beginning, the Capslock is off, it's at a state of lower characters, you are required that after typing it should still be at lower state.
There are three kinds operations:

  1. Type a character, the screen will print a character at corresponding state (lower or upper). You hit the keyboard once.
  2. Press Capslock, switch the state of the keyboard. You hit the keyboard once.
  3. Press Shift with some character, the screen will print a character at a opposite state. You hit the keyboard twice. e.g. It will print 'P' when you press Shift + 'p'.

Example

Input:
"Hello"
Output:
6

Clarification

The type steps:Shift + 'h', 'e', 'l', 'l', 'o'.

Notice

The length of the string is N, 1≤N≤10​5​​.

Input test data (one parameter per line)How to understand a testcase?

解法1:
这题想了好久。我开始的解法不对。参考的别人的思路。

这题难在有几种组合混在一起。对于每个字母,无论大写或小写,都可以通过按CAP键与否和按SHIFT键与否来实现。这种情况可以通过DP来解决,保证不会遗漏中间的情况。

双序列DP: upper[i]表示当前为第i个字符,CAP键按下时所需的最少按键,lower[i]表示当前为第i个字符,CAP键未按下时所需的最少按键。那么,

当第i个字符为大写字母时:
upper[i]如果由upper[i-1]来实现,其值直接加1即可。因为CAP键已经按下,不需再按SHIFT键,
upper[i]如果由lower[i-1]来实现,其值必须加2。因为CAP键未按下,必须要按下CAP键,再敲第i个字符。
lower[i]如果由upper[i-1]来实现,其值必须加2。因为CAP键已经按下,必须要再按CAP键消掉大写功能,再直接敲第i个字符。
lower[i]如果由lower[i-1]来实现,其值必须加2。因为CAP键未按下,必须要按SHIFT键来实现大写。

当第i个字符为小写字母时:
upper[i]如果由upper[i-1]来实现,其值必须加2。因为CAP键已经按下,必须再按SHIFT键来实现小写。
upper[i]如果由lower[i-1]来实现,其值必须加2。因为CAP键未按下,必须要按下CAP键,再敲第i个字符。
lower[i]如果由upper[i-1]来实现,其值必须加2。因为CAP键已经按下,必须要再按CAP键消掉大写功能,再直接敲第i个字符。
lower[i]如果由lower[i-1]来实现,其值直接加1即可。因为CAP键未按下,也不需要按SHIFT键就可以实现小写。

代码如下:

class Solution {
public:
    /**
     * @param str: the string you wanna print.
     * @return: return the minimum times you need to hit the keyboard.
     */
    int minimumTyping(string &str) {
        int n = str.size();
        vector<int> upper(n);
        vector<int> lower(n);
        
        if (isupper(str[0])) {
            upper[0] = 2;
            lower[0] = 2;
        } else {
            upper[0] = 2;
            lower[0] = 1;
        }

        for (int i = 1; i < n; ++i) {
            if (isupper(str[i])) {
                upper[i] = min(upper[i - 1] + 1, lower[i - 1] + 2);
                lower[i] = min(upper[i - 1] + 2, lower[i - 1] + 2);
            } else {
                upper[i] = min(upper[i - 1] + 2, lower[i - 1] + 2);
                lower[i] = min(upper[i - 1] + 2, lower[i - 1] + 1);
            }
        }
        
        return lower.back();
    }
};

 

### Minimum Snap 的基本概念 Minimum Snap 是一种用于轨迹规划的技术,旨在最小化加速度变化率(即“抖动”),从而实现平滑的运动路径。这种方法特别适用于无人机和其他自动化设备,在这些应用中,平稳而高效的飞行路径至关重要。 #### 关键特点 - **平滑性**:通过优化高阶导数来减少不必要的振动和能量消耗。 - **效率**:相比传统的线性或抛物线插值方法,能够提供更加节能且快速响应的路径规划方案[^1]。 ### Minimum Snap 入门教程 #### 安装依赖库 要开始使用 Minimum Snap 进行编程实践,首先需要安装一些必要的 Python 库: ```bash pip install numpy scipy matplotlib ``` #### 创建简单的二维空间中的 Minimum Snap 轨迹 下面是一个创建简单二维平面内从起点到终点之间遵循 minimum snap 准则的轨迹的例子: ```python import numpy as np from scipy.optimize import minimize def min_snap_cost_function(params, waypoints): """定义目标函数""" t = params[:len(waypoints)-1] p = params[len(waypoints)-1:] cost = 0 for i in range(len(t)): dt = (t[i+1]-t[i]) if i < len(t)-1 else 1e-6 # 计算位置差分 dp = waypoints[i+1] - waypoints[i] # 构建多项式系数矩阵 A 和 B A = [[dt**j / factorial(j) for j in range(8)]] b = [dp[k]/factorial(k+1)*(-1)**k for k in range(2)] try: invA = np.linalg.inv(A) z = np.dot(invA,b) jerk_squared_sum = sum([z[j]**2 * dt**(7-j)/(factorial(7-j)) for j in range(8)]) cost += jerk_squared_sum except Exception as e: pass return cost def generate_trajectory(waypoints): initial_guess = list(np.ones((len(waypoints),))) + list(sum([[wp]*8 for wp in waypoints], [])) res = minimize(min_snap_cost_function, initial_guess, args=(waypoints,), method='Powell') optimized_params = res.x times = optimized_params[:len(waypoints)-1] positions = [] velocities = [] prev_time = 0. for idx, time_step in enumerate(times[:-1]): current_position = waypoints[idx] next_position = waypoints[idx+1] duration = time_step-prev_time velocity_change = (next_position-current_position)/duration positions.append(current_position) velocities.append(velocity_change) prev_time = time_step return {'positions': positions, 'velocities': velocities} if __name__ == "__main__": waypoints = [(0., 0.), (5., 3.), (-2., 9.)] # Example Way Points trajectory_data = generate_trajectory(waypoints) print("Positions:", trajectory_data['positions']) print("Velocities:", trajectory_data['velocities']) ``` 这段代码展示了如何基于给定的关键点计算满足 minimum snap 条件下的最优时间间隔以及对应的位置和速度序列。注意这里简化了很多细节以便于理解核心原理;实际工程实践中还需要考虑更多因素如物理约束、安全边界等[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值