速通ACM省铜第七天 赋源码(Sponsor of Your Problems)
目录
引言:
Sponsor of Your Problems
题意分析
逻辑梳理
代码实现
结语:
引言:
今天讲的便是昨天所说的那道cf1500的题,但今天我看完这道题,我觉得甚至没有之前几天1400.1300的那些题的难度高,那么,接下来,我们就进入 今天的算法讲解————>
Sponsor of Your Problems
那么按照惯例,我们先来看一下题目
题意分析
这是题目的链接Problem - 2121E - Codeforces
不想跳转的可看下图
题目其实很简单,就是给你俩个数l和r,然后还有一个x位于这俩个数之间,然后有个式子f(l,r)的值就是l和r相同的个数(一位一位的比对),然后问你f(l,x)+f(x,r)的最小值,输出即可,题目很简单,接下来我们进行逻辑的梳理
特别注意:l和r俩个数的位数是相同的,我一开始没看到这个,还想复杂了
逻辑梳理
首先我们不用管x取什么(这么多数,还要找最小情况,再考虑这个那完蛋了),只需要知道x是中间一个数就可以了,我们只需要对l和r俩个数进行分析即可
那么我们接下来就通过图文来进行分析
首先我们先看直接的数据进行分析,如图
先看第一位,因为都是2,所以x的第一位肯定也是2(介于l和r之间),所以不管x怎么取,最少的次数肯定会+2(x和r的一次与x和l的一次),随后看第二位,也同理,所以依旧次数+2.然后我们看第三位 ,0与3相差了不止1,所以为了让次数最少x可以在1,2里任取,此时,最少的次数就不会加了,因为和l和r都不一样,在这一位不同后,后面的剩余位便可以随便取了,只要不跟l和r一样即可,所以这俩个数的结果就是4
那么我们再来看一种情况,如题
先看第一位,依旧是次数+2,第二位只相差1,所以不管x取什么,都会与其中一位相同,所以次数+1,当出现这种情况时候,后面必须要大的是那个数的当前位是9,小的那个数的当前位是0(下一段讲为什么),若满足这个条件,就次数加1,直到不满足这个条件时,循环结束,输出次数即可
至于为什么,通过看图就很容易理解,若是9和0的话,在上一位的基础上,基本这一位也固定在了9和0之间,但若不是9和0,在前面那个条件下,不管该位置上是那俩个数,都有转圜之机了,可以选出不为这俩个数的情况了
那么,对于数的分析已经分析完了,那我们来对整个逻辑进行梳理
从第一位开始遍历下去会有三种情况
第一种 就是这俩位的数字大小相等,这个时候次数+2接着往下遍历
第二种 就是这俩位数的数字大小不相等,且相差大于了1(0,9是特殊),那么就直接结束循环,次数不加
第三种 就是这俩位数的数字相差为1,次数就+1,若满足这中情况,第一二种情况就不用管了,直接接着往下遍历,判断接下来的位是否大的那个数位0,小的那个数位9,若满足就次数+1接着遍历,若不满足则结束循环即可
最后输出得到的次数即可,那么逻辑已经梳理完了,接下来我们进入代码实现的环节
代码实现
这里推荐用字符串来进行数据的存储与判断,这样好操作一点,因为是从数据的头开始处理的,那么别的需要注意的就没有了,接下来请看AC源码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <queue>
#include <vector>
using namespace std;int t;
string a;
string b;void solve()
{cin >> b >> a;int ans = 0;int xixi = 0;for (int i = 0; i < b.size(); i++){if (xixi){if (a[i] == '0' && b[i] == '9'){ans++;continue;}break;}if (a[i] == b[i]){ans += 2;continue;}if (a[i] == '0')a[i] += 10;if (a[i] - b[i] > 1 || b[i] - a[i] > 1){break;}if (a[i] - b[i] == 1 || b[i] - a[i] == 1){xixi = 1;ans++;}}cout << ans << endl;
}int main()
{cin >> t;while (t--){solve();}return 0;
}
那么,这题就讲完啦
结语:
今日算法讲解到此结束啦,希望对你们有所帮助,谢谢观看,如果觉得不错可以分享给朋友哟。
· 不得不说这题划分为1500的难度还是水分太大了,感觉撑死应该就1300或者1200