UVa10665 Diatribe against Pigeonholes

 Diatribe against Pigeonholes 

Background

In an anonymous town there is a carpenter, the only one in many kilometres, specialized in making pieces of furniture (and famous for being a bit stingy with the screws). This carpenter made a shelving for a company, using only two screws.

The Problem

We have a lineal set of N similar pigeonholes (numbered 1, 2, 3, ..., N, with 1< N < 26) forming a shelving, where Nworkers of a company receive their mail. Each worker has an associated capital letter, ABC, and so on, until Z if necessary. Your task is to associate each worker with one pigeonhole. As the shelving is fragile in the middle  (i.e., pigeonhole (N+1)/2) due to the stinginess of the carpenter, we have to put the mail of each worker as follows: the heaviest ones, the further from the middle of the shelving, in order to protect the shelving. You must suppose that all parcels weigh the same weight.

The Input

The first line of the input contains an integer, M, indicating the number of test cases. For each test case, the first line indicates the number N of workers (and pigeonholes) of the company, 1 < N < 26. One more line follows, containing a string of capital letters, corresponding each one with a parcel destinated to the corresponding worker, finished with a “#” character. For example, the string ABABBAA# means that worker A receives 4 parcels, and B receives 3. Characters not corresponding with valid workers must be omitted.

The Output

For each test case, the output should consist of two lines, the first one showing the secuence of workers corresponding with the obtained ordering, separated with one blank space. If there is more than one solution, you have to output the alphabetically first. The second line will consist of the number of parcels in each pigeonhole, in the same order of the previous line, and also separated with one blank space.

Sample Input

4
5
BDCECDCBCBCDECDABCEDVBCDBCDBCDABCAED#
7
BGFADCEDGFCDEGCFCGDGCXXDAEDACEACEGFAGFCEDGCEDGBCD#
24
AABACDEDFGHMMJNTBNHGTDFACCDLLPPPERRAMMMMKKKKJJJHHHAAAAGGGQQQLLLLPPPAA#
10
PDJFGEDFANGEHIAEJBHJGEDGJGJEINDFJHEIEDGHFFGHDHGFHAJGIE#

Sample Output

C B A E D
11 8 3 4 9
C D A B F E G
10 9 5 2 5 7 9
A L G D C B E F I O S U V W X N R T Q J K H M P
11 6 5 4 3 2 2 2 0 0 0 0 0 0 0 2 2 2 3 4 4 5 6 6
E H D A B C I F J G
8 7 6 3 1 0 4 6 7 9



这道题toolkit分类的时候说是DP题,但我认为这题更偏向于贪心,这一题要分类讨论,当遇到cnt相同的时候 将字典序小的放在前面,字典序大的放在后面,当cnt相同的个数为奇数的时候,将剩下一个,将这剩下的一个与后面的一段cnt相同的字母集合的第一个字母进行比较,如果大于它,将剩下的那个放在后面,将它放在前面,否则,将剩下的那个放在前面,将下一个集合中的最后一个放在后面(贪心的策略)。依次进行

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;
struct cha{
    char ch;
    int cnt;
    friend bool operator < (cha a,cha b){
        if(a.cnt!=b.cnt)
            return a.cnt>b.cnt;
        else
            return a.ch<b.ch;
    }
    cha(char ch = '_',int cnt = 0):ch(ch),cnt(cnt){}
};
cha ans[30];
vector<cha> vch;
int cnt[30];
int n;
void init(){
    vch.clear();
    memset(cnt,0,sizeof cnt);
    for(int i = 0; i < 30; i++)
        ans[i] = cha('_',0);
}
int main(){
    int ncase;
    cin >> ncase;
    while(ncase--){

        scanf("%d",&n);
        init();
        char ch;
        while(cin >> ch && ch!='#')cnt[ch-'A']++;
        for(int i = 0; i < n; i++) vch.push_back(cha(i+'A',cnt[i]));
        sort(vch.begin(),vch.end());
        int i = 0,j = 0,k = 0,kg = -1;
        while(i < n){
            k = i;
            while(vch[k].cnt==vch[i].cnt&&k<n) k++;
            int ti = k;
            k--;
            if(kg != -1){
                if(vch[kg].ch > vch[i].ch){
                    ans[j] = vch[i],ans[n-j-1] = vch[kg];
                    j++;
                    i++;
                }else{
                    ans[j] = vch[kg],ans[n-j-1] = vch[k];
                    j++;
                    k--;
                }
            }
            while(i<k){
                if(vch[i].ch<vch[k].ch) ans[j] = vch[i],ans[n-j-1]=vch[k];
                else ans[j] = vch[k],ans[n-j-1] = vch[i];
                j++;
                i++;
                k--;
            }
            if(i==k) kg = k;
            else kg = -1;
            i = ti;
        }
        if(ans[(n-1)/2].ch=='_')
            ans[(n-1)/2] = vch[kg];
        cout<<ans[0].ch;
        for(int i = 1; i < n; i++) cout<<" "<<ans[i].ch;
        cout<<endl;
        cout<<ans[0].cnt;
        for(int i = 1; i < n; i++) cout<<" "<<ans[i].cnt;
        cout<<endl;
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值