C - Slot Strategy - AtCoder Beginner Contest 252
C - Slot Strategy
AtCoder Beginner Contest 252
题意
现有一slot machine,上面有\(N\)个转轴,对应\(N\)个按钮,将每个转轴展开,记所得的字符串为\(S_i\),规定\(S_i\)的长度都为10,其中0~9十个数字各出现一次 。
每秒钟,可以选择是否“按按钮”(每次只能按一个按钮),每次按按钮,转轴就会停在当前时间的下一个位置(越界则轮换)。
问最少需要多少秒,才能使所有转轴停在同一个位置。
思路
大思路:某个位置的字符 → 一个数字 → 所有数字
所有转轴都应停在同一位置, 因此每次我们只需要考虑同一个数字.
假设我们现在希望slot machine停在0处。
设\(count(0, j)\)表示,在\(N\)个字符串中,满足第\(j\)个字符是\(0\)的字符串的个数
1. 考察第\(j\)个位置需要的时间
首先,为使所有第\(j\)个字符是‘0’的转轴停在‘\(0\)’处,我们至少需要在不同的时间\(t'\), 重复\(count(0, j)\)次按按钮,则其满足
反之,当 \(t <10\times (count(0, j) - 1) + j\)时,不可能在这\(t\)秒钟内,使所有转轴停在\(0\)处。
简而言之, \(t'_j\)是使所有第\(j\)个字符是‘0’的转轴停在‘\(0\)’处所花的最少时间.
栗子
我们稍加改造样例1
// Sample Input 1
3
1937458062
8124690357
2385760149
// Sample Input 1'
4
1937458062
8124690357
2385760149
2385760149
对于样例1, AtCoder已经解释了, 使slot machine都停在\(8\)需要的时间最少.
下面观察我们的\(1'\), 我们继续考虑\(8\)这个选项, 我们发现第三第四行, 8的位置是相同的'2', 也就是\(count(8, 2) = 2\)
下面计算使两处第二个位置的8停下至少花多长时间.
我们在第2秒的时候会按下第三个按钮(此时不能同时按第四个), 在第12秒的时候按下第四个按钮, 至少要花12秒.
另一方面, 应用我们的公式, 我们至少花
的时间, 和我们的模拟是一致的.
2. 考察对于'0'这个数字,需要花多少时间
对于每一个\(j\), 都对应了不同的\(t'_j\), 它们是彼此独立的, 因此我们需要的最少时间, 就是这里面的最大值.
综上,我们至少需要
的时间,使所有转轴停在\(0\)处.
3. 推广, 得到最终答案
依次类推, 将上式中的0换成其它数字, 我们就能得到其它数字所需要的最少时间.
答案即它们当中的最小值.
\(count(0, j)\)表示,在\(N\)个字符串中,满足第\(j\)个字符是\(k\)的字符串的个数
代码实现
垃圾的代码
#include<iostream>
#include<set>
#include<string>
#include<algorithm>
using namespace std;
const int N = 101, INF = 0x3f3f3f3f;
int n;
multiset<int> S[N];
int size_max[11][11];
int main(void){
cin >> n;
for (int i = 1; i <= n; i ++ ){
string str;
cin >> str;
for (int j = 1; j <= 10; j ++ ){
int num = str[j - 1] - '0';
S[num].insert(j);
size_max[num][j] ++ ;
}
}
int ans = INF;
for (int i = 0; i <= 9; i ++ ){
int res = 0;
multiset<int>::iterator it;
for(it = S[i].begin(); it != S[i].end(); it++)
{
int x = S[i].count(*it);
res = max(res, (x - 1) * 10 + *it - 1);
}
ans = min(ans, res);
}
cout << ans;
return 0;
}
漂亮的代码
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
const int N = 101, INF = 0x3f3f3f3f;
int cnt[N][11];
int n;
int main(void){
cin >> n;
for (int i = 0; i < n; i ++ ){
string str;
cin >> str;
for(int j = 0; j < 10; j ++ ){
int x = str[j] - '0';
cnt[x][j + 1] ++ ;
}
}
int ans = INF;
for (int i = 0; i < 10; i ++ ){
int res = 0;
for (int j = 1; j <= 10; j ++ ){
res = max(res, (cnt[i][j] - 1) * 10 + j - 1);
}
ans = min(ans, res);
}
cout << ans ;
return 0;
}