拼多多0515 笔试第三题
3、多多的字符翻转
多多君在研究十六进制字符串的翻转关系,每次可以选择字符串中的某个子串,进行一次整体变大或变小的翻转。例如: "ABCD"选择中间2个字符的子串"BC",变大翻转会变成: "ACDD",变小翻转会变成:"AABD"。特别的,字符0'变小的翻转会变成字符F',同理字符'F'的变大翻转会变成字符0',以此循环往复。多多君想知道,给定两个字符串A和B,最少可以用多少次翻转使得字符串A变成字符串B。
输入描述
第一行,1个整数T,代表测试用例的组数。( 1 <=T<= 1,000 ) 对于每一组测试用例,共一行:2个字符串A和B。(两个字符串由数字或大写的字母组成,数据保证两个字符串长度相同,并且不超过4)
输出描述
对于每组测试用例,输入一行,一个整数,表示字符串A翻转成字符串B的最少步数。
示例1
输入
5 AB BC 01 F0 ABCD BDEE AAA FFF 0AF ABC
输出
1 1 2 5 10
思路
首先B串的每个字符减去A串对应的每个字符,如:
AB BC 可以得到1、1 01 F0 可以得到-1、-1 ABCD BDEE 可以得到 1、2、2、1 AAA FFF 0AF ABC
然后对得到的序列遍历,翻转,使得最后为全0,如:
1、1 同时减去1 得到全0 -1、-1 同时加1 得到全0 3、5、2、4 先同时减2,得到新的序列 1、3、0、2,再对前两个同时减1,得到0、2、0、2,再分别对第二个和第四个同时减去2,因此翻转次数为:2+1+2+2
#include<iostream>
#include<vector>
#include<string>
#include<unordered_map>
using namespace std;
unordered_map<char, int> mmap = {{'0',0},{'1',1},{'2',2},{'3',3},{'4',4},{'5',5},{'6',6},{'7',7},{'8',8},
{'9',9},{'A',10}, {'B',11},{'C',12}, {'D',13}, {'E',14}, {'F',15}};
int helper(string& A, string& B) {
vector<int> vec(4);
int n = A.size();
for (int i = 0; i < n; i++) {
vec[i] = mmap[B[i]] - mmap[A[i]] > 8 ? mmap[B[i]] - mmap[A[i]] - 16 : mmap[B[i]] - mmap[A[i]];
}
int count = 0;
for (int i = 0; i < 4; i++) {
while (vec[i] != 0) {
//小于0
if (vec[i] < 0) {
int t_max = vec[i];
int j;
for (j = i + 1; j < 4; j++) {
if (vec[j] >= 0) {
break;
}
else {
t_max = max(t_max, vec[j]);
}
}
for (int z = i; z < j; z++) {
vec[z] += abs(t_max);
}
count += abs(t_max);
}
//大于0
else {
int t_min = vec[i];
int j;
for (j = i + 1; j < 4; j++) {
if (vec[j] <= 0) {
break;
}
else {
t_min = min(t_min, vec[j]);
}
}
for (int z = i; z < j; z++) {
vec[z] -= t_min;
}
count += t_min;
}
}
}
return count;
}
int main() {
string A, B;
int n;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> A >> B;
cout << endl;
cout << helper(A, B) << endl;
}
return 0;
}
#拼多多笔试#
查看8道真题和解析