P4447分组
一开始贪心思路不对且根本没考虑重复,无脑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;
}