2022-06-03每日刷题打卡
代码源——每日一题
一个小整数 - 题目 - Daimayuan Online Judge
HoshiYo是一个魔术师。他擅长使用魔术,但他不擅长数学。在魔法学校的数学课上,HoshiYo学习了整数的知识。他突然发现一个有趣的事情:用他强大的魔法,他可以通过重新排列数字来改变一个整数。
从形式上看,从0∼9的每个数字,第i个数字是ai,说明有ai个这样的数。HoshiYo想得到一个符合以下规则的整数。
所有给定的数字都被使用。
第一个数不能是0,除非这个数就是0。
相邻的数字不能相同。
HoshiYo想知道他能用这些数字得到的最小整数是多少。
输入
给出10个整数a0,a1,…,a9(0≤ai≤105),表示不同数字的数量。可以保证1≤所有数总和≤105。
输出
输出HoshiYo能在一行中得到的最小整数。如果没有解决方案,就用一行字输出-1。
样例输入
2 0 1 0 0 1 0 2 0 0
样例输出
205707
问题解析
这题其实挺好想的,如果没写出来可能是想复杂了。
我们先分析一下,这里无非就四种情况:
1、数量最多的那个数,数量是其它数的总和还多1以上
2、数量最多的那个数,数量是其它数的总和还多1
3、数量最多的那个数,数量正好等于其它数的总和
4、数量最多的那个数,数量小于其它数的总和
(以下最多数量的数我们简称x,其它数量的数简称y)
如果是第一种情况,那么显然无论我们怎么样,必然会有相邻的数相同的情况出现,直接输出-1。
如果是第二种情况,那么第一个数只能是x,然后一个y,一个x这样交替放,并且末尾也会是这个最多数,即:xyxy……xyx。
如果是第三种情况,那么第一个数可以是x也可以是y,即:xyxy……xy或yxyx……yx这样子。
如果是第四种情况,我们可以随便摆,只要保证相邻数不相同即可。
情况分析完毕,我们开始想题:
我们每次先遍历一遍这十个数,计算一下数量最多的数和其它数量数总和的关系,然后我们根据关系来取数:
如果是第一种情况,我们直接输出-1结束程序即可;如果是第二种情况,我们第一个数只能是这个最多数量的数;如果是第三、四种情况,我们可以取这十个数中最小的那个数(不强迫选,那为了数最小,我们肯定要选小的数放在前面),但要注意不能和上一个数相同。而且对于第2、3、4种情况,如果这是我们取的第一个数,那么这个数不能是0,因为除了0本身我们不能有前导0(建议一开始特判一下只有一个0,其它数都没有的情况),如果我们必须要取0了,那也是输出-1。
取完一个数后,我们把那个数的个数-1,然后回到开头进行下一步。
数的总个数是2e4,我们每次取一个数要遍历一下这十个数,然后就可以根据情况判断了,总复杂度也才1e5。
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#define endl '\n'
#define int ll
typedef long long ll;
typedef pair<ll, ll>PII;
const int N = 1e6 + 50;
ll n, v[10];
bool dfs(vector<int>& res)
{
int sum = 0, mx = 0, ans = -1;
for (int i = 0; i < 10; i++)
{
sum += v[i];
if (v[i] > mx)
{
mx = v[i];
ans = i;
}
}
if (sum == 0)return true;
sum -= mx;
if (sum + 1 == mx)
{
if (ans == 0 && res.empty())
{
return false;
}
else
{
res.push_back(ans);
v[ans]--;
}
}
else if (sum + 1 < mx)
{
return false;
}
else
{
int u = res.size() == 0 ? 1 : 0;
int k = u == 1 ? -1 : res.back();
for (int i = u; i < 10; i++)
{
if (v[i] != 0 && i != k)
{
res.push_back(i);
v[i]--;
break;
}
}
}
return dfs(res);
}
signed main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int sum = 0;
for (int i = 0; i < 10; i++)
cin >> v[i], sum += v[i];
if (v[0] == 1 && sum == 1)
{
cout << 0 << endl;
return 0;
}
vector<int>res;
if (dfs(res))
{
if (res.empty())cout << -1;
else for (auto i : res)cout << i;
cout << endl;
}
else
{
cout << -1 << endl;
}
return 0;
}