P4447分组

发布时间 2023-10-23 17:27:57作者: 加固文明幻景

一开始贪心思路不对且根本没考虑重复,无脑sort后直接排组玄学了70pts。

#include <iostream>
#include <algorithm>

using namespace std;

int n;
int cnt, ans = 0x7fffffff;
int a[100010];

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	sort(a + 1, a + n + 1);
	for (int i = 2; i <= n; i++) {
		cnt++;
		if (a[i] - a[i - 1] > 1) {
			ans = min(ans, cnt);
			cnt = 0;
		}
	}
	if (a[n] - a[n - 1] > 1) {
		ans = min(1, ans);
	}
	if (ans == 0x7fffffff) {
		ans = n;
	}
	cout << ans;
	return 0;
}

之后看了这位哥的题解,明白了正确的贪心思路。

通过桶思想存重复的数,然后类比俄罗斯方块消层来分组:
每次处理最底层,下一个相邻数的重复次数如果比上一个多,就划入组中,桶对应的计数器自减,如果下一个相邻数的重复次数比上一个少,就不划入组中。
联想俄罗斯方块,这种做法能尽可能地让上层齐平,从而使最少数量的组长度最大。

代码实现

#include<map>
#include<iostream>
using namespace std;

map<int,int> m;
int ans = 0x7fffffff, n, temp;

int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> temp;
		++m[temp];
	}
	while(!m.empty())
	{
		map<int, int>::iterator i = m.begin(), j = m.begin();
		(*i).second--,j++,temp = 1;
		for (;j != m.end() && (*j).first == (*i).first + 1 && (*j).second > (*i).second; i++, j++)
		{
			temp++;
			(*j).second--;
		}
		i=m.begin();
		while(i!=m.end()&&(*i).second==0){
			m.erase((*i++).first);
		}	
		ans = min(ans, temp); 
	}
	cout << ans; 
	return 0;
}