题目描述
给定一些不同的十进制数字,您可以通过选择这些数字的一个非空子集并以某种顺序编写它们来形成一个整数。剩余的数字可以以某种顺序写下来形成第二个整数。除非结果整数为 0,否则整数可能不以数字 0 开头。
例如,如果给定数字 0, 1, 2, 4, 6 和 7,您可以编写整数对 10 和 2467。当然,有许多方法可以形成这样的整数对:210 和 764,204 和 176 等。最后一对整数之间的差的绝对值为 28,事实证明,通过上述规则形成的其他整数对都无法实现更小的差。
输入格式
输入的第一行包含要遵循的案例数。
对于每个案例,输入一行,其中包含至少两个但不超过 10 个十进制数字。(十进制数字为 0, 1, …, 9。)一个输入行中的数字不会重复出现。数字将以递增顺序出现,用一个空格分隔。
输出格式
对于每个测试案例,在一行上写下可以从给定数字中按照上述规则编写的两个整数的最小绝对差。
输入输出样例 #1
输入 #1
1
0 1 2 4 6 7
输出 #1
28
提交链接
Smallest Difference
思路分析
题目允许任意顺序组合数字,只要组成两个整数,所以:
-
我们不能固定使用某种顺序(例如输入顺序)
-
所有可能的数字组合与顺序都可能影响结果。
我们必须考虑所有可能的排列(即:全排列)来保证正确性。
思考:对于一种排列是否需要枚举每一个分割点?
不需要。我们要的是两个数的最小差值。那两个数相差最小的时候,是它们的值本身最接近的时候。所以:只要对每个排列 “从中间分割” 即可。
1️⃣ 提取所有数字 去掉空格,仅保留数字 处理输入格式
string s;
getline(cin, s);
vector<int> a;
for (int i = 0; i < s.size(); i++)
{if (s[i] >= '0' && s[i] <= '9')a.push_back(s[i] - '0');
}
2️⃣ 排序后全排列 枚举所有排列方式 保证覆盖所有顺序
do
{} while (next_permutation(a.begin(), a.end()));
3️⃣ 对每个排列进行中间划分 分成两段构成两个整数 保证平均划分,逼近最小差
do
{int s1 = 0, s2 = 0, pos = a.size() / 2;// 0 ~ pos - 1 vs pos ~ a.size() - 1for (int i = 0; i < a.size(); i++){if (i < pos)s1 = s1 * 10 + a[i];elses2 = s2 * 10 + a[i];}} while (next_permutation(a.begin(), a.end()));
4️⃣ 检查前导0 多位数不能以 0 开头 保证合法性
do
{int s1 = 0, s2 = 0, pos = a.size() / 2;if (a[0] == 0 || a[pos] == 0)continue;// 0 ~ pos - 1 vs pos ~ a.size() - 1for (int i = 0; i < a.size(); i++){if (i < pos)s1 = s1 * 10 + a[i];elses2 = s2 * 10 + a[i];}} while (next_permutation(a.begin(), a.end()));
5️⃣ 计算差值并更新最小值 最终目标是最小绝对差值 比较每种合法组合
int mi = 1e9;
do
{int s1 = 0, s2 = 0, pos = a.size() / 2;if (a[0] == 0 || a[pos] == 0)continue;// 0 ~ pos - 1 vs pos ~ a.size() - 1for (int i = 0; i < a.size(); i++){if (i < pos)s1 = s1 * 10 + a[i];elses2 = s2 * 10 + a[i];}mi = min(mi, abs(s1 - s2));} while (next_permutation(a.begin(), a.end()));
完整代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
using namespace std;
int t, x;
int main()
{cin >> t;getchar();while (t--){string s;getline(cin, s);vector<int> a;for (int i = 0; i < s.size(); i++){if (s[i] >= '0' && s[i] <= '9')a.push_back(s[i] - '0');}if (a.size() == 2){cout << abs(a[0] - a[1]) << endl;continue;}int mi = 1e9;// 全排列do{int s1 = 0, s2 = 0, pos = a.size() / 2;// 0 ~ pos - 1 vs pos ~ a.size() - 1if (a[0] == 0 || a[pos] == 0)continue;for (int i = 0; i < a.size(); i++){if (i < pos)s1 = s1 * 10 + a[i];elses2 = s2 * 10 + a[i];}mi = min(mi, abs(s1 - s2));} while (next_permutation(a.begin(), a.end()));cout << mi << endl;}return 0;
}