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' \bmod 10 = 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秒.

另一方面, 应用我们的公式, 我们至少花

\[t'_2 = \{ 10 \times(count(0, j) - 1) \} + j = 10 \times 1 + 2 = 12 (s) \]

的时间, 和我们的模拟是一致的.

2. 考察对于'0'这个数字,需要花多少时间

对于每一个\(j\), 都对应了不同的\(t'_j\), 它们是彼此独立的, 因此我们需要的最少时间, 就是这里面的最大值.

综上,我们至少需要

\[\max _{j=0,1, \ldots, 9}(10 \times(\operatorname{count}(0, j)-1)+j) \]

的时间,使所有转轴停在\(0\)处.

3. 推广, 得到最终答案

依次类推, 将上式中的0换成其它数字, 我们就能得到其它数字所需要的最少时间.

答案即它们当中的最小值.

\[\min _{k=0,1, \ldots, 9}\left(\max _{j=0,1, \ldots, 9}(10 \times(\operatorname{count}(k, j)-1)+j)\right) \]

\(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;
}
posted @ 2022-05-22 10:09  tsrigo  阅读(163)  评论(0编辑  收藏  举报