思路

先贴一下 26 个字母的分布:

ABC DEF
GHI JKL MNO
PQRS TUV WXYZ

规则很清晰,就是字母在哪一块的第几个位置就按几下,相邻的字母如果在同一块上面就需要等待 2 个时间段,所以我们需要做的第一步其实是应该存一下每个字母所在的位置,然后就很容易求了。

#include<iostream>
#include<vector>

using namespace std;

class Block{
public:
    int block;
    int pos;
public:
    Block(int block, int pos) : block(block), pos(pos){}
};

int getCost(string s, vector<Block>& chars){
    int cnt = 0, n = s.size();
    for(int i = 0; i < n; i ++){
        cnt += chars[s[i] - 'a'].pos;
        if(i > 0 && chars[s[i] - 'a'].block == chars[s[i - 1] - 'a'].block) 
            cnt += 2;
    }
    return cnt;
}

int main(){
    string s;
    vector<Block> chars;
    // 初始化字母的位置
    for(int i = 0; i < 18; i ++)
        chars.emplace_back(i / 3, i % 3 + 1);
    chars.emplace_back(5, 4); chars.emplace_back(6, 1);
    chars.emplace_back(6, 2); chars.emplace_back(6, 3);
    chars.emplace_back(7, 1); chars.emplace_back(7, 2);
    chars.emplace_back(7, 3); chars.emplace_back(7, 4);
    while(cin >> s){
        cout << getCost(s, chars) << endl;
    }
    return 0;
}

更简单的做法,这个就不用存每个字母的位置了,因为如果两个字母在一个按钮里面,那个 pos 肯定是连续的,所以字母的距离和 pos 之差应该相等。

#include<iostream>
#include<string>
using namespace std;
int main(){
    int key[26] = {1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,4,1,2,3,1,2,3,4};
    string str;
    while(cin >> str){
        int count = key[str[0]-'a'];
        for(int i = 1; i < str.size(); i ++){
            count += key[str[i]-'a'];
            if(key[str[i]-'a']-key[str[i-1]-'a'] == str[i]-str[i-1])//判断是否在同一个按键上
                count+=2;
        }
        cout << count << endl;
    }
    return 0;
}