1 条题解

  • 0
    @ 2025-4-10 10:53:15

    解题思路

    题目要求从最终消息推断出原始消息,给定信使的顺序。每个信使在传递消息时都会对消息进行特定的变换。为了从最终消息推断出原始消息,我们需要对每个信使的操作进行逆向操作。具体步骤如下:

    1. 定义每个信使的逆向操作

      • J先生:将消息的所有字符向左旋转一位。逆向操作是将消息的所有字符向右旋转一位。
      • C小姐:将消息的所有字符向右旋转一位。逆向操作是将消息的所有字符向左旋转一位。
      • E先生:将消息的左半部分与右半部分交换。如果消息的字符数是奇数,中间的字符保持不变。逆向操作是将消息的右半部分与左半部分交换。
      • A先生:将消息反转。逆向操作是将消息再次反转。
      • P博士:将消息中的所有数字加1。逆向操作是将消息中的所有数字减1。
      • M先生:将消息中的所有数字减1。逆向操作是将消息中的所有数字加1。
    2. 逆向操作的实现

      • 对于每个信使的操作,实现其逆向操作。
      • 从最终消息开始,按照信使顺序的逆序,依次应用每个信使的逆向操作。
    3. 输入处理

      • 读取输入数据,包括数据集的数量、每个数据集的信使顺序和最终消息。
      • 对每个数据集,依次应用逆向操作,最终输出推断出的原始消息。

    代码实现

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <vector>
    #include <queue>
    #include <map>
    #include <set>
    #include <ctime>
    #include <string>
    using namespace std;
    typedef long long ll; // 定义长整型变量的简写
    #define INF 0x3f3f3f3f // 定义无穷大的值
    #define maxn 1111 // 定义数组的最大长度
    #define pi acos(-1.0) // 定义圆周率
    
    // 将字符串的最后一个字符移到第一个位置(J先生的逆向操作)
    void J(string& str)
    {
    	char ch = str[str.length() - 1]; // 获取字符串的最后一个字符
    	str.erase(str.length() - 1, 1); // 删除字符串的最后一个字符
    	str.insert(0, 1, ch); // 将字符插入到字符串的开头
    }
    
    // 将字符串的第一个字符移到最后一个位置(C小姐的逆向操作)
    void C(string& str)
    {
    	char ch = str[0]; // 获取字符串的第一个字符
    	str.erase(0, 1); // 删除字符串的第一个字符
    	str.insert(str.length(), 1, ch); // 将字符插入到字符串的末尾
    }
    
    // 将消息的左半部分与右半部分交换(E先生的逆向操作)
    void E(string& str)
    {
    	int len = str.length(); // 获取字符串的长度
    	string tmp = str; // 临时保存原始字符串
    	if (len % 2) // 如果字符串长度为奇数
    	{
    		char ch = tmp[len / 2]; // 获取中间的字符
    		str.erase(0, len / 2 + 1); // 删除从开头到中间字符(包含)的部分
    		str.append(1, ch); // 将中间字符追加到字符串末尾
    		str.append(tmp, 0, len / 2); // 将原始字符串的前半部分追加到末尾
    	}
    	else // 如果字符串长度为偶数
    	{
    		str.erase(0, len / 2); // 删除前半部分
    		str.append(tmp, 0, len / 2); // 将前半部分追加到末尾
    	}
    }
    
    // 将字符串反转(A先生的逆向操作)
    void A(string& str)
    {
    	reverse(str.begin(), str.end()); // 使用标准库函数反转字符串
    }
    
    // 将消息中的所有数字减1(P博士的逆向操作)
    void P(string& str)
    {
    	int len = str.length(); // 获取字符串的长度
    	for (int i = 0; i < len; i++) // 遍历字符串
    		if (str[i] >= '0' && str[i] <= '9') // 如果是数字字符
    		{
    			str[i]--; // 减一
    			if (str[i] < '0') // 如果小于0
    				str[i] = '9'; // 变为9
    		}
    }
    
    // 将消息中的所有数字加1(M先生的逆向操作)
    void M(string& str)
    {
    	int len = str.length(); // 获取字符串的长度
    	for (int i = 0; i < len; i++) // 遍历字符串
    		if (str[i] >= '0' && str[i] <= '9') // 如果是数字字符
    		{
    			str[i]++; // 加一
    			if (str[i] > '9') // 如果大于9
    				str[i] = '0'; // 变为0
    		}
    }
    
    // 根据指令对字符串进行逆向操作
    void solve(char dir, string &str)
    {
    	if (dir == 'J') // 如果指令是'J'
    		C(str); // 调用C函数(J的逆向操作)
    	else if (dir == 'C') // 如果指令是'C'
    		J(str); // 调用J函数(C的逆向操作)
    	else if (dir == 'E') // 如果指令是'E'
    		E(str); // 调用E函数(E的逆向操作)
    	else if (dir == 'A') // 如果指令是'A'
    		A(str); // 调用A函数(A的逆向操作)
    	else if (dir == 'P') // 如果指令是'P'
    		M(str); // 调用M函数(P的逆向操作)
    	else // 如果指令是'M'
    		P(str); // 调用P函数(M的逆向操作)
    }
    
    int main()
    {
    	int n; // 定义测试用例的数量
    	char dir[7]; // 定义指令字符串
    	scanf("%d", &n); // 读取测试用例数量
    	while (n--) // 遍历每个测试用例
    	{
    		scanf("%s", dir); // 读取指令字符串
    		int len = strlen(dir); // 获取指令字符串的长度
    		string msg; // 定义消息字符串
    		cin >> msg; // 读取消息字符串
    		for (int i = len - 1; i >= 0; i--) // 从指令字符串的末尾开始遍历
    		{
    			solve(dir[i], msg); // 对消息字符串进行逆向操作
    		}
    		cout << msg << endl; // 输出最终结果
    	}
    	return 0; // 程序结束
    }
    

    注释说明

    • J、C、E、A、P、M函数:分别实现了每个信使的逆向操作。
    • solve函数:根据信使的指令调用相应的逆向操作函数。
    • main函数:读取输入数据,依次对每个数据集的消息进行逆向操作,最终输出推断出的原始消息。
    • 1

    信息

    ID
    1042
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    12
    已通过
    1
    上传者