Diatribe against Pigeonholes |
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.
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, A, B, C, 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 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.
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.
4
5
BDCECDCBCBCDECDABCEDVBCDBCDBCDABCAED#
7
BGFADCEDGFCDEGCFCGDGCXXDAEDACEACEGFAGFCEDGCEDGBCD#
24
AABACDEDFGHMMJNTBNHGTDFACCDLLPPPERRAMMMMKKKKJJJHHHAAAAGGGQQQLLLLPPPAA#
10
PDJFGEDFANGEHIAEJBHJGEDGJGJEINDFJHEIEDGHFFGHDHGFHAJGIE#
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; }
原文:http://blog.csdn.net/ghevinn/article/details/18766861