UVA - 11100 The Trip, 2007

题目

思路:

最少要多少个包裹既是某个数出现的最多次。

接下来才是重头戏,怎么输出序列呢?

我第一次的做法是用优先队列一次次慢慢输出,虽然结果正确,但代码冗长。

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;

const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;

int n, m, k;

vi p;

map<int, int> mp;

typedef struct Node{
	int v, t;
	Node(int a, int b){
		v = a;
		t = b;
	}
	bool operator < (const Node &rhs) const{
		if(t == rhs.t)
			return v > rhs.v;
		return t < rhs.t;
	}
}Node;

int main(void)
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << setprecision(10) << fixed;
	while(cin >> n, n){
		p.clear();
		p.resize(n);
		for(int i = 0; i < n; i++)
			cin >> p[i];
		sort(p.begin(), p.end());
		if(mp.size())
			cout << endl;
		int res = 0;
		mp.clear();
		for(int i = 0; i < n; i++){
			mp[p[i]]++;
			res = max(res, mp[p[i]]);
		}
		cout << res << endl;
		priority_queue<Node> q;
		queue<Node> buf;
		for(auto it = mp.begin(); it != mp.end(); ++it)
			q.push(Node(it ->first, it ->second));
		vi num;
		num.resize(res);
		for(int i = 0; i < res; i++)
			num[i] = n / res + (i + 1 <= n % res);
		for(int i = 0; i < res; i++){
			while(!buf.empty()){
				q.push(buf.front());
				buf.pop();
			}
			vi save;
			for(int j = 0; j < num[i]; j++){
				save.push_back(q.top().v);
				if(q.top().t - 1)
					buf.push(Node(q.top().v, q.top().t - 1));
				q.pop();
			}
			sort(save.begin(), save.end());
			for(int j = 0; j < (int)save.size(); j++){
				if(j)
					cout << " ";
				cout << save[j];
			}
			cout << endl;
		}
	}
	cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
	return 0;
}

第二次就聪明了,因为输出的序列总数和出现最多次的数的次数是一样的,所以这样做就可以了。

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;

const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;

int n, m, k;

map<int, int> mp;
vi p;

int main(void)
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << setprecision(10) << fixed;
	while(cin >> n, n){
		p.clear();
		p.resize(n);
		for(int i = 0; i < n; i++)
			cin >> p[i];
		sort(p.begin(), p.end());
		if(mp.size())
			cout << endl;
		mp.clear();
		int res = 0;
		for(int i = 0; i < n; i++)
			res = max(res, ++mp[p[i]]);
		cout << res << endl;
		for(int i = 0; i < res; i++){
			cout << p[i];
			for(int j = i + res; j < n; j += res)
				cout << " " << p[j];
			cout << endl;
		}
	}
	cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
	return 0;
}

因为这n段序列一定每段都包含出现最多次的数。

 

未来可期。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值