题解:洛谷 P1765 手机

【题目来源】

洛谷:P1765 手机 - 洛谷

【题目描述】

一般的手机的键盘是这样的:

要按出英文字母就必须要按数字键多下。例如要按出 \(x\) 就得按 \(9\) 两下,第一下会出 \(w\),而第二下会把 \(w\) 变成 \(x\)\(0\) 键按一下会出一个空格。

你的任务是读取若干句只包含英文小写字母和空格的句子,求出要在手机上打出这个句子至少需要按多少下键盘。

【输入】

一行句子,只包含英文小写字母和空格,且不超过 \(200\) 个字符。

【输出】

一行一个整数,表示按键盘的总次数。

【输入样例】

i have a dream

【输出样例】

23

【核心思想】

  1. 问题分析:给定一个只包含小写字母和空格的字符串(长度不超过 200),需要计算在九宫格手机键盘上输入该字符串所需的总按键次数。每个字母的按键次数取决于它在键盘上的位置(如 abc 在按键 2 上,分别按 1、2、3 次;sz 特殊,需要按 4 次;空格按 1 次)。本质是字符到按键次数的映射问题。

  2. 算法选择

    • 映射表 + 遍历:预先建立一个数组 m,将每个字符映射到其对应的按键次数。然后遍历字符串,累加每个字符的按键次数。
    • 实现方式:代码中使用 int m[300] 作为映射表,手动初始化每个字母的按键次数(按九宫格键盘布局)。
  3. 关键步骤

    • 读入:使用 getline(cin, s) 读入可能包含空格的整行。
    • 构建映射表
      • 'a''r':按 3 个一组循环映射为 1、2、3(即 abc → 1、2、3;def → 1、2、3;...;pqr → 1、2、3)。
      • 's''z':特殊处理,映射为 4。
      • 't''y':同样按 3 个一组循环映射为 1、2、3(tuv → 1、2、3;wxyz 中的 wxy → 1、2、3;z 已特殊处理)。
      • 空格:映射为 1。
    • 统计:遍历字符串,ans += m[s[i]]
    • 输出ans
  4. 时间/空间复杂度

    • 时间复杂度:\(O(L)\)\(L\) 是字符串长度。
    • 空间复杂度:\(O(1)\),映射表固定大小。
  5. 映射与键盘布局

    • 九宫格键盘映射:熟悉手机键盘布局是解题前提。按键 2: abc,3: def,4: ghi,5: jkl,6: mno,7: pqrs,8: tuv,9: wxyz。每个字母所需的按键次数即它在该键上的位置(从 1 开始),但 sz 分别在 7 和 9 键的第 4 个位置,所以需要按 4 次。
    • 直接模拟 vs 映射表:手动构建映射表是最直接的方法,也可以使用数组预定义所有字母的按键次数,但代码中通过循环初始化减少重复。
    • 空格处理:题目明确 0 键按一次输出空格,所以空格对应次数为 1。
    • 适用场景:这类“键盘输入模拟”是字符串处理中的常见题型,核心是准确建立字符到操作次数的映射。

【算法标签】

入门 #字符串入门

【代码详解】

#include <bits/stdc++.h>  // 包含标准库头文件(万能头文件)
using namespace std;      // 使用标准命名空间

int main()
{
    string s;            // 定义字符串:存储输入的字符串
    int ans = 0;         // 定义变量:存储最终按键次数总和
    int m[300];          // 定义数组:存储每个字符对应的按键次数
    int mark = 1;        // 定义变量:辅助赋值变量

    getline(cin, s);     // 读取整行输入(包含空格)

    // 初始化字母a-r的按键次数(循环1-3)
    for (int i = 'a'; i <= 'r'; i++)
    {
        m[i] = mark;     // 赋值当前字母的按键次数
        mark++;          // 辅助变量递增
        if (mark == 4)   // 每3个字母循环一次
            mark = 1;
    }

    // 特殊处理字母s、z和空格
    m['s'] = 4;          // 字母s需要按4次
    m['z'] = 4;          // 字母z需要按4次
    m[' '] = 1;          // 空格需要按1次

    mark = 1;            // 重置辅助变量
    // 初始化字母t-y的按键次数(循环1-3)
    for (int i = 't'; i <= 'y'; i++)
    {
        m[i] = mark;     // 赋值当前字母的按键次数
        mark++;          // 辅助变量递增
        if (mark == 4)   // 每3个字母循环一次
            mark = 1;
    }

    // 计算字符串中所有字符的按键次数总和
    for (int i = 0; i < s.length(); i++)
    {
        ans += m[s[i]];  // 累加当前字符的按键次数
    }

    cout << ans;         // 输出总按键次数

    return 0;            // 程序正常结束
}

【运行结果】

i have a dream
23
posted @ 2026-08-30 09:18  团爸讲算法  阅读(15)  评论(0)    收藏  举报