POJ1002解题报告

来源:互联网 发布:投资保姆软件下载 编辑:程序博客网 时间:2024/06/06 17:28

本博客与RayXXZhang的博客保持同步更新,转载请注明来自RayXXZhang的博客-POJ1002解题报告

题目概览

标题

487-3279

要求

  • Time Limit: 2000MS

  • Memory Limit: 65536K

题目描述

Businesses like to have memorable telephone numbers. One way to make a telephone number memorable is to have it spell a memorable word or phrase. For example, you can call the University of Waterloo by dialing the memorable TUT-GLOP. Sometimes only part of the number is used to spell a word. When you get back to your hotel tonight you can order a pizza from Gino’s by dialing 310-GINO. Another way to make a telephone number memorable is to group the digits in a memorable way. You could order your pizza from Pizza Hut by calling their ‘three tens’ number 3-10-10-10.

The standard form of a telephone number is seven decimal digits with a hyphen between the third and fourth digits (e.g. 888-1200). The keypad of a phone supplies the mapping of letters to numbers, as follows:

A, B, and C map to 2
D, E, and F map to 3
G, H, and I map to 4
J, K, and L map to 5
M, N, and O map to 6
P, R, and S map to 7
T, U, and V map to 8
W, X, and Y map to 9

There is no mapping for Q or Z. Hyphens are not dialed, and can be added and removed as necessary. The standard form of TUT-GLOP is 888-4567, the standard form of 310-GINO is 310-4466, and the standard form of 3-10-10-10 is 310-1010.

Two telephone numbers are equivalent if they have the same standard form. (They dial the same number.)

Your company is compiling a directory of telephone numbers from local businesses. As part of the quality control process you want to check that no two (or more) businesses in the directory have the same telephone number.

输入

The input will consist of one case. The first line of the input specifies the number of telephone numbers in the directory (up to 100,000) as a positive integer alone on the line. The remaining lines list the telephone numbers in the directory, with each number alone on a line. Each telephone number consists of a string composed of decimal digits, uppercase letters (excluding Q and Z) and hyphens. Exactly seven of the characters in the string will be digits or letters.

输出

Generate a line of output for each telephone number that appears more than once in any form. The line should give the telephone number in standard form, followed by a space, followed by the number of times the telephone number appears in the directory. Arrange the output lines by telephone number in ascending lexicographical order. If there are no duplicates in the input print the line:

No duplicates.

输入示例

12

4873279

ITS-EASY

888-4567

3-10-10-10

888-GLOP

TUT-GLOP

967-11-11

310-GINO

F101010

888-1200

-4-8-7-3-2-7-9-

487-3279

输出示例

310-1010 2

487-3279 4

888-4567 3

解题报告

分析

需要将输入还原成数字,可以有几种方法:

  1. 可以构建字符和数字映射的哈希表:

    table['A'] = table['B'] = table['C'] = 1;...
  2. 可以使用 switch 语句:

    switch(oneChar) {    case 'A':    case 'B':    case 'C':        ...}

需要将解析出的数字放入哈希表或者数组中以便统计出现个数。如果使用C++的map,则最后输出时还能实现自动的排序。

C++的map容器学习

头文件

使用map需引用map头文件

#include<map>

声明

map<int, string> map1;

C++11前map的初始化只能通过[]下标操作或者insert函数实现,C++11引入了新的map初始化方式,可以通过如下方式进行初始化:

map<int, string> map1 = {{1, "A"}, {2, "B"}};

插入

插入操作可以使用[]下标操作或者insert函数。两者的区别是当要的键之前存在时,[]会更新原来的值,而insert则不会更新,并且返回值为 false

insert有很多个重载,其中最常用的一个重载接受一个pair类型作为参数,可以使用 make_pair 来创建pair:

map1.insert(make_pair(1, "A"));

C++11可以通过emplace函数添加新元素:

map1.emplace(1, "A");

查找

查找通过find函数。find函数返回一个迭代器,通过判断迭代器是否为end来确认是否查找到了指定的元素:

map<int, string>::iterator it = map1.find(1);if(it != map1.end()) {    // 找到相应元素   }

访问

通过使用[]下标操作访问元素,c++11可以通过at函数来访问元素。

需要注意的一点是使用[]下标操作有副作用,即如果该键不存在,会在该键上插入一个有默认值的元素。

删除

删除使用earse函数,传入要删除的键即可

遍历

map通过迭代器遍历:

for(map<int, string>::iterator it = map1.begin();it != map1.end(); ++it) {    // it->first 是键    // it->second 是值}

c++11还能通过以下方法遍历:

for(auto it: map1) {    // it.first 是键    // it.second 是值}

其他

其他函数及详细说明可以参考C++ map官方文档

POJ的一些注意事项

编译

C++的编译可以使用POJ提交选项中的C++或者G++编译器,其中C++是VC++的编译器,G++是GNU的编译器。两者均不支持C++11特性。
有些题目使用C++能通过,但G++会超时,有时又相反,因此超时或内存占用过大的情况下可以试着换一下编译器。

IO

C++的cin和cout的运行时间比C中的scanf和printf要长,容易超时。且在本题中按字符读取而不是按字符串读取必定超时(未验证,该说法来自POJ1002-487-3279)

STL

使用STL效率会降低一些

源码

#include<map>#include<string>#include<iostream>#include<iomanip>using namespace std;class PhoneNumberList {public:    explicit PhoneNumberList() :numMap() { };    void add(string numStr) {        int number = parse(numStr);        map<int, int>::iterator it = numMap.find(number);        if (it == numMap.end()) {            numMap.insert(make_pair(number, 1));        }        else {            it->second++;        }    }    friend ostream & operator<<(ostream &os, PhoneNumberList &list) {        bool duplicate = false;        for (map<int, int>::iterator i = list.numMap.begin(); i != list.numMap.end(); ++i) {            if (i->second != 1) {                os << setfill('0') << setfill('0') << setw(3) << i->first / 10000 << "-" << setfill('0') << setw(4) << i->first % 10000 << " " << i->second << endl;                duplicate = true;            }        }        if (duplicate == false) {            os << "No duplicates." << endl;        }        return os;    };private:    map<int, int> numMap;    int parse(string numStr) const {        int result = 0;        int length = numStr.length();        for (int i = 0; i < length; ++i) {            char *c = &numStr[i];            switch (*c) {            case 'A':            case 'B':            case 'C':                result = result * 10 + 2;                break;            case 'D':            case 'E':            case 'F':                result = result * 10 + 3;                break;            case 'G':            case 'H':            case 'I':                result = result * 10 + 4;                break;            case 'J':            case 'K':            case 'L':                result = result * 10 + 5;                break;            case 'M':            case 'N':            case 'O':                result = result * 10 + 6;                break;            case 'P':            case 'R':            case 'S':                result = result * 10 + 7;                break;            case 'T':            case 'U':            case 'V':                result = result * 10 + 8;                break;            case 'W':            case 'X':            case 'Y':                result = result * 10 + 9;                break;            default:                if (*c >= '0' && *c <= '9') {                    result = result * 10 + *c - '0';                }                break;            }        }        return result;    }};int main() {    int lines;    PhoneNumberList phoneNumberList;    cin >> lines;    string item;    for (int i = 0; i < lines; ++i) {        cin >> item;        phoneNumberList.add(item);    }    cout << phoneNumberList;}

参考页面

C++11遍历map

C++ map[ ]=与insert操作不同

C++学习之map类型

C++ map官方文档

0 0
原创粉丝点击