diff --git a/src/7/17/T634195.cpp b/src/7/17/T634195.cpp index 0074521..b68f926 100644 --- a/src/7/17/T634195.cpp +++ b/src/7/17/T634195.cpp @@ -1,121 +1,122 @@ -// #include -// #include -// #include - -// using ll = int64_t; -// ll n,ans{}; -// std::string s1,s2; - -// bool isBig(char c){ -// return 'A'<=c&&c<='Z'; -// } - -// void swapBS(char &c){ -// if(isBig(c)){ -// c=c-'A'+'a'; -// }else{ -// c=c-'a'+'A'; -// } -// } - -// ll rn(ll idx){ -// ll ans{}; -// if(s2[idx]>=s1[idx]){ -// ans=s2[idx]-s1[idx]; -// }else{ - -// } -// // return -// } - -// int main(){ -// std::cin>>n; -// std::cin>>s1>>s2; -// s1=' '+s1; -// s2=' '+s2; - -// for(ll i=s1.size()-1;i>=1;i--){ -// if(isBig(s1[i])!=isBig(s2[i]))ans++; -// swapBS(s1[i]); - -// } -// } - -// /* -// 1. 改变大小写 -// 2. 前后移动字典序 -// 1. 如果向右越界那么前面一个字母的字典序+1 -// 2. 向左则反之 -// 3. 第一位不用考虑这些 -// 4. 类似于26进制 -// */ - -#include -#include -#include +#include #include -using namespace std; +#include +#include +#include +#include +#include +#include +#include + using ll = int64_t; -int main() { - ios::sync_with_stdio(false); - cin.tie(0); +ll n; +std::string s1,s2; +std::vector>> dp; +/* +dp[k][i]=tuple(ll w,ll jt) +k从右往左第k个字符 +i减少增加 +w消耗的次数 +jt 0不变,1进位,-1退位 +*/ - int n; - cin >> n; - string s1, s2; - cin >> s1 >> s2; - - ll co = 0; - vector A(n), B(n); - for (int i = 0; i < n; i++) { - if (isupper(s1[i])) { - A[i] = s1[i] - 'A'; - } else { - A[i] = s1[i] - 'a'; - } - if (isupper(s2[i])) { - B[i] = s2[i] - 'A'; - } else { - B[i] = s2[i] - 'a'; - } - bool s1_upper = isupper(s1[i]); - bool s2_upper = isupper(s2[i]); - if (s1_upper != s2_upper) { - co++; +std::tuple rw(ll i){ + ll ans{}; + ll jt{}; + char c = s1[i]; + while(c!=s2[i]){ + ans++; + if(c=='z'){ + jt=1; + c='a'; + continue; } + c++; } - - vector diff(n); - for (int i = 0; i < n; i++) { - diff[i] = B[i] - A[i]; + return {ans,jt}; +} +std::tuple lw(ll i){ + ll ans{}; + ll jt{}; + char c = s1[i]; + while(c!=s2[i]){ + ans++; + if(c=='a'){ + jt=-1; + c='z'; + continue; + } + c--; } + return {ans,jt}; +} - for (int i = n - 1; i >= 1; i--) { - ll x = diff[i]; - ll temp = x + 12; - ll q; - if (temp >= 0) { - q = temp / 26; - } else { - q = temp / 26; - if (temp % 26 != 0) { - q--; +ll setr(char &c){ + ll jt{}; + if(c=='z'){ + c='a'; + jt=1; + }else{ + c=c+1; + } + return jt; +} + +ll setl(char &c){ + ll jt{}; + if(c=='a'){ + jt=-1; + c='z'; + }else{ + c=c-1; + } + return jt; +} + +int main(){ + std::cin>>n>>s1>>s2; + + s1=' '+s1; + s2=' '+s2; + dp.resize(s1.size()+1,std::vector>(2,std::pair(std::numeric_limits::max(),0))); + dp[s1.size()][0].first = dp[s1.size()][1].first = 0; + for(ll k=s1.size()-1;k>=1;k--){ + ll nw{}; + if(isupper(s1[k]) != isupper(s2[k])){ + nw++; + } + s1[k]=tolower(s1[k]); + s2[k]=tolower(s2[k]); + for(ll i=0;i<(ll)dp[k+1].size();i++){ + if(dp[k+1][i].second==1){ + setr(s1[k]); + auto[tlw,tljt] = lw(k); + auto[trw,trjt]=rw(k); + dp[k][0].first=std::min(dp[k][0].first,tlw+dp[k+1][i].first+nw); + if(dp[k][0].first==tlw+dp[k+1][i].first+nw)dp[k][0].second=tljt; + dp[k][1].first=std::min(dp[k][1].first,trw+dp[k+1][i].first+nw); + if(dp[k][1].first==trw+dp[k+1][i].first+nw)dp[k][1].second=trjt; + setl(s1[k]); + }else if(dp[k+1][i].second==-1){ + setl(s1[k]); + auto[tlw,tljt] = lw(k); + auto[trw,trjt]=rw(k); + dp[k][0].first=std::min(dp[k][0].first,tlw+dp[k+1][i].first+nw); + if(dp[k][0].first==tlw+dp[k+1][i].first+nw)dp[k][0].second=tljt; + dp[k][1].first=std::min(dp[k][1].first,trw+dp[k+1][i].first+nw); + if(dp[k][1].first==trw+dp[k+1][i].first+nw)dp[k][1].second=trjt; + setr(s1[k]); + }else{ + auto[tlw,tljt] = lw(k); + auto[trw,trjt]=rw(k); + dp[k][0].first=std::min(dp[k][0].first,tlw+dp[k+1][i].first+nw); + if(dp[k][0].first==tlw+dp[k+1][i].first+nw)dp[k][0].second=tljt; + dp[k][1].first=std::min(dp[k][1].first,trw+dp[k+1][i].first+nw); + if(dp[k][1].first==trw+dp[k+1][i].first+nw)dp[k][1].second=trjt; } } - ll r = x - 26 * q; - diff[i] = r; - diff[i - 1] += q; } - - ll mo = 0; - for (int i = 0; i < n; i++) { - mo += abs(diff[i]); - } - - ll ans = mo + co; - cout << ans << endl; - - return 0; + std::cout< #include #include +#include +#include using namespace std; int main() { - ios::sync_with_stdio(false); - cin.tie(0); - int n; cin >> n; - string s1, s2; - cin >> s1 >> s2; + string s_top, s_bottom; + cin >> s_top >> s_bottom; - long long case_ops = 0; - vector A(n), B(n); - for (int i = 0; i < n; i++) { - if (isupper(s1[i])) { - A[i] = s1[i] - 'A'; + vector val_S(n), val_T(n); + vector case_S(n), case_T(n); + + // 预处理:提取每个字符的值和大小写 + for (int i = 0; i < n; ++i) { + char c = s_top[i]; + if (islower(c)) { + val_S[i] = c - 'a'; + case_S[i] = 0; } else { - A[i] = s1[i] - 'a'; - } - if (isupper(s2[i])) { - B[i] = s2[i] - 'A'; - } else { - B[i] = s2[i] - 'a'; - } - bool s1_upper = isupper(s1[i]); - bool s2_upper = isupper(s2[i]); - if (s1_upper != s2_upper) { - case_ops++; + val_S[i] = c - 'A'; + case_S[i] = 1; } } - vector diff(n); - for (int i = 0; i < n; i++) { - diff[i] = B[i] - A[i]; + for (int i = 0; i < n; ++i) { + char c = s_bottom[i]; + if (islower(c)) { + val_T[i] = c - 'a'; + case_T[i] = 0; + } else { + val_T[i] = c - 'A'; + case_T[i] = 1; + } } - for (int i = n - 1; i >= 1; i--) { - long long x = diff[i]; - long long temp = x + 12; - long long q; - if (temp >= 0) { - q = temp / 26; - } else { - q = temp / 26; - if (temp % 26 != 0) { - q--; + // 计算大小写成本 + int case_cost = 0; + for (int i = 0; i < n; ++i) { + if (case_S[i] != case_T[i]) { + case_cost++; + } + } + + // 计算值操作成本(从右向左动态规划) + int value_cost = 0; + int carry_in = 0; // 初始进位为0 + + for (int i = n - 1; i >= 0; --i) { + int x = val_S[i] + carry_in; + int best_cost = 1e9; + int best_carry_out = 0; + + // 尝试三种进位输出: -1, 0, 1 + for (int cand_carry_out : {-1, 0, 1}) { + int m = val_T[i] + 26 * cand_carry_out - x; + int abs_m = abs(m); + if (abs_m < best_cost) { + best_cost = abs_m; + best_carry_out = cand_carry_out; } } - long long r = x - 26 * q; - diff[i] = r; - diff[i - 1] += q; + + value_cost += best_cost; + carry_in = best_carry_out; // 传递进位到左侧 } - long long move_ops = 0; - for (int i = 0; i < n; i++) { - move_ops += abs(diff[i]); - } - - long long ans = move_ops + case_ops; - cout << ans << endl; + int total_cost = case_cost + value_cost; + cout << total_cost << endl; return 0; } ``` -### 代码解释 -1. **输入处理**: - - 读取字符串长度 `n` 和上下排字符串 `s1`、`s2`。 - -2. **大小写操作计数**: - - 遍历每个字符,将字母转换为0-25的整数值(忽略大小写),并记录大小写是否相同。若不同,则增加 `case_ops`。 +### 示例解释 +输入示例: +``` +5 +AbCDx +dECba +``` +- **大小写成本**:位置0(A vs d)、1(b vs E)、3(D vs b)大小写不同,成本为3。 +- **值操作成本计算**: + - 值序列:S = [0,1,2,3,23], T = [3,4,2,1,0]。 + - 从右向左处理: + - i=4: x=23, T[4]=0 → min |m|=3 (carry_out=1)。 + - i=3: x=3+1=4, T[3]=1 → min |m|=3 (carry_out=0)。 + - i=2: x=2, T[2]=2 → min |m|=0 (carry_out=0)。 + - i=1: x=1, T[1]=4 → min |m|=3 (carry_out=0)。 + - i=0: x=0, T[0]=3 → min |m|=3 (carry_out=0)。 + - 值成本总和:3+3+0+3+3=12。 +- **总成本**:3(大小写) + 12(值操作) = 15,与输出一致。 -3. **差分数组初始化**: - - 计算目标字母值与初始字母值的差值,存入 `diff` 数组。 - -4. **进位调整**: - - 从右向左(低位到高位)调整 `diff` 数组。对每个位置计算调整值 `q` 和余数 `r`,确保 `r` 在[-12, 13]区间内,并将进位 `q` 传递到左侧位置。 - -5. **移动操作计数**: - - 调整后,`diff` 数组各元素的绝对值之和即为移动操作次数 `move_ops`。 - -6. **输出结果**: - - 总操作数为 `move_ops` 和 `case_ops` 之和。 - -这种方法高效地处理了字母移动引发的进位传播,并通过调整差分数组最小化操作次数,结合独立的大小写转换操作,得到最优解。 \ No newline at end of file +此算法高效处理了进位传播和大小写匹配,确保最小操作次数。 \ No newline at end of file