题目来源:http://poj.org/problem?id=1055
题目大意:
每封信都有一个zip-code, 由5位数字构成,可以通过将zip-code相同或相近的信件打包来节省成本。打包规则是:5位数字完全相同的10-15封可组成一个包(5-digit bundles),或者将前3位数字相同的信件打包,同样10-15份一包(3-digit bundles)。优先分配为5-digit bundles, 其次3-digit bundles。不能被打包的信件为first class letters。要求输出打包方案。
输入:没行一个zip-code,但并非每个都是合法的。合法的zip-code恰好由5位数字组成,不能全为0.
输出:按上述要求输出打包方案,格式见输出,合法的bundles和letters需要按数字大小顺序输出。。
Sample Input
95864 95864 95864 95867 95920 9j876 95616 95616 95747 95814 95818 95818 8976 95818 95818 95819 95819 00000 95819 95819 95819 95819 95819 95825 95825 95825 95825 95825 95826 95826 95826 95826 95826 95826 95827 8976 95833 95833 95833 95833 95819 95819 95819 95819 95833 95833 95833 95864 95864 95864 123456 95864 95864 95864 95864
Sample Output
ZIP LETTERS BUNDLES 95819 11 1 95864 10 1 958xx 25 2 95616 2 0 95747 1 0 95920 1 0 TOTALS 50 4 INVALID ZIP CODES 9j876 8976 00000 123456
本题虽在POJ的第一版,但是却人气颇低..确实不太有意思, 主要思想就是桶排序。
输出格式非常坑人,很容易错,题目描述得也不是特别清楚,最后的非法zip-code需要判重且按出现顺序输出。按照提述规则,似乎有可能出现多解的情况,但是测试数据没有太刁难,invalid zip-code的长度最长只到6,zip-code最高位不为0,用最简单的策略(对于一些比较偏的case可能不能过的)也可以AC。所以,这样的题随便看看就好了..
1 //////////////////////////////////////////////////////////////////// 2 // POJ1055 BULK MAILING 3 // Memory: 1212K Time: 0MS 4 // Language: C++ Result : Accepted 5 /////////////////////////////////////////////////////////////////// 6 7 #include <cstdio> 8 #include <string> 9 //#include <algorithm> 10 11 using namespace std; 12 13 struct Bundle { 14 int letter_cnt, bun_cnt; 15 }; 16 17 Bundle buns[100000]; 18 char buffer[10], invalid_record[100000][10]; 19 int invalid_cnt, zip_cnt[100000], total_letters, total_buns; 20 21 bool M[100000]; 22 23 bool validity_check(char buffer[]){ 24 25 //位数检查 26 if (strlen(buffer) != 5) { 27 return false; 28 } 29 30 //数字检查 31 for (int i = 0; i < 5; i++) { 32 if (buffer[i] < '0' || buffer[i] > '9') { 33 return false; 34 } 35 } 36 37 //全0检查 38 bool flag = true; 39 for (int i = 0; i < 5; ++i) { 40 if (buffer[i] != '0') { 41 flag = false; 42 break; 43 } 44 } 45 if (flag) { 46 return false; 47 } 48 return true; 49 } 50 51 void process1(void) { 52 53 //同5位10份以上打包 54 for (int i = 10000; i <= 99999; ++i) { 55 if (zip_cnt[i] >= 10){ 56 while (zip_cnt[i] >= 15) { 57 buns[i].letter_cnt += 15; 58 ++buns[i].bun_cnt; 59 total_letters += 15; 60 ++total_buns; 61 zip_cnt[i] -= 15; 62 } 63 if (zip_cnt[i] >= 10) { 64 buns[i].letter_cnt += zip_cnt[i]; 65 ++buns[i].bun_cnt; 66 total_letters += zip_cnt[i]; 67 ++total_buns; 68 zip_cnt[i] = 0; 69 } 70 } 71 } 72 73 //按序输出 74 printf("ZIP LETTERS BUNDLES "); 75 puts(""); 76 for (int i = 10000; i <= 99999; ++i) { 77 if (buns[i].letter_cnt != 0) { 78 printf("%d%12d%12d ", i, buns[i].letter_cnt, buns[i].bun_cnt); 79 } 80 } 81 puts(""); 82 83 //清空三位数的桶 84 for (int i = 100; i <= 999; ++i) { 85 buns[i].letter_cnt = buns[i].bun_cnt = 0; 86 } 87 } 88 89 void process2(void) { 90 91 //同3位10份以上打包 92 for (int i = 100; i <= 999; ++i) { 93 int temp[100][2]; 94 int cnt = 0, letter_cnt = 0; 95 for (int j = 0; j <= 99; ++j) { 96 int num = i * 100 + j; 97 if (zip_cnt[num] > 0) { 98 temp[cnt][0] = num; 99 temp[cnt][1] = zip_cnt[num]; 100 letter_cnt += zip_cnt[num]; 101 zip_cnt[num] = 0; 102 ++cnt; 103 } 104 } 105 while (letter_cnt >= 15) { 106 ++buns[i].bun_cnt; 107 ++total_buns; 108 buns[i].letter_cnt += 15; 109 total_letters += 15; 110 letter_cnt -= 15; 111 } 112 if (letter_cnt >= 10) { 113 ++buns[i].bun_cnt; 114 ++total_buns; 115 buns[i].letter_cnt += letter_cnt; 116 total_letters += letter_cnt; 117 letter_cnt = 0; 118 } 119 while (letter_cnt > 0) { 120 if (temp[cnt - 1][1] >= letter_cnt) { 121 zip_cnt[temp[cnt - 1][0]] += letter_cnt; 122 break; 123 } else { 124 zip_cnt[temp[cnt - 1][0]] += temp[cnt - 1][1]; 125 letter_cnt -= temp[cnt - 1][1]; 126 --cnt; 127 } 128 } 129 if (buns[i].letter_cnt > 0) { 130 printf("%dxx%12d%12d ", i, buns[i].letter_cnt, buns[i].bun_cnt); 131 } 132 } 133 puts(""); 134 } 135 136 void process3(void) { 137 //first class 输出 138 for (int i = 10000; i <= 99999; ++i) { 139 if (zip_cnt[i] > 0){ 140 printf("%d%12d%12d ", i, zip_cnt[i], 0); 141 total_letters += zip_cnt[i]; 142 } 143 } 144 puts(""); 145 } 146 147 void output_invalid(void) { 148 //非法zip-code输出 149 printf("INVALID ZIP CODES "); 150 for (int i = 0; i < invalid_cnt; ++i) { 151 bool flag = true; 152 for (int j = 0; j < i; ++j) { 153 if (strcmp(invalid_record[i], invalid_record[j]) == 0) { 154 flag = false; 155 } 156 } 157 if (flag) { 158 printf("%s ", invalid_record[i]); 159 } 160 } 161 162 } 163 int main(void) { 164 invalid_cnt = 0; 165 while (scanf("%s", buffer) != EOF) { 166 if (validity_check(buffer)) { 167 168 //桶排序 169 int num = 0; 170 for (int i = 0; i < 5; ++i) { 171 num = num * 10 + buffer[i] - '0'; 172 } 173 ++zip_cnt[num]; 174 } else { 175 strcpy(invalid_record[invalid_cnt], buffer); 176 ++invalid_cnt; 177 } 178 } 179 180 process1(); 181 process2(); 182 process3(); 183 printf("TOTALS%11d%12d ", total_letters, total_buns); 184 output_invalid(); 185 186 return 0; 187 }