1.题目描述

http://poj.org/problem?id=1002

2.解题过程

按部就班来解题的话,这个题目很容易写出来,这是我的第一个版本的代码,思路是读入一行电话字符串,均转化为整型数字存入vector结构,然后进行排序,顺序统计即可发现重复的电话号码及次数。

   1: /*author :lipan

   2:   date: 2013.7.23

   3:   email: areslipan@163.com

   4:  */

   5:  

   6: #include <iostream>

   7: #include <vector>

   8: #include <iterator>

   9: #include <string>

  10: #include <algorithm>

  11:  

  12: using namespace std;

  13:  

  14: int cvtString2Int(string & str);

  15: void normalizedOutput(int tel,int &count);

  16: void showDump(vector<int> & telNum);

  17:  

  18: bool sortAsc(const int & v1 ,const int & v2)

  19: {

  20:     return v1<v2;

  21: }

  22: /*

  23: void showIntVector(vector<int> & in)

  24: {

  25:     vector<int>::iterator iter;

  26:     cout<<endl;

  27:     for(iter = in.begin(); iter!= in.end();++iter)

  28:     {

  29:         cout<< *iter<<endl;

  30:     }

  31: }*/

  32: int main()

  33: {

  34:     int count;

  35:  

  36:     vector<int> input_tel;

  37:  

  38:     cin>>count;

  39:  

  40:     string curTel;

  41:     int curTelInt;

  42:     for(int i=0;i<count;++i)

  43:     {

  44:         cin>> curTel;

  45:         input_tel.push_back(cvtString2Int(curTel));

  46:  

  47:     }

  48:   

sort(input_tel.begin(),input_tel.end(),sortAsc);

  49:     //showIntVector(input_tel);

  50:     showDump(input_tel);

  51:     return 1;

  52: }

  53:  

  54: int cvtString2Int(string & str)

  55: {

  56:     int ret = 0;

  57:     for(int i = 0; i< str.length(); ++i)

  58:     {

  59:         if(str[i] == '-') continue;

  60:         

  61:         int digit;

  62:         if(str[i]>='0'&&str[i]<='9')

  63:         {

  64:             digit = str[i] - '0';

  65:         }

  66:         else

  67:         {

  68:             if (str[i] <'Z' &&str[i]>'Q')

  69:             {

  70:                 digit = (str[i] - 'Q')/3 + 7;

  71:             }

  72:             else

  73:                 if(str[i]>='A' &&str[i]<'Q')

  74:                 {

  75:                     digit = (str[i] - 'A')/3 + 2;

  76:                 }

  77:         }

  78:  

  79:         ret = 10 * ret + digit;

  80:  

  81:     }    

  82:  

  83:     return ret;

  84: }

  85:  

  86: void normalizedOutput(int tel,int &count)

  87: {

  88:     cout<<endl;

  89:     vector<int> result;

  90:     int bitNum  = 0;

  91:     while(tel!=0)

  92:     {

  93:         result.push_back(tel%10);

  94:         tel /=10;

  95:         bitNum ++;

  96:     }

  97:  

  98:     int hy = 0;

  99:     while(bitNum<7)

 100:     {

 101:         cout << '0';

 102:         hy++;

 103:         if(hy == 3)cout << '-';

 104:         bitNum ++;

 105:     }

 106:  

 107:     vector<int>::reverse_iterator  iter;

 108:     for(iter = result.rbegin();iter!= result.rend();++iter)

 109:     {

 110:         cout<<*iter;

 111:         hy++;

 112:         if(hy == 3)cout<<'-';

 113:     }

 114:  

 115:     cout<<" "<<count;

 116:     

 117: }

 118: void showDump(vector<int> & telNum)

 119: {

 120:     int flag = 0;

 121:     int count = 1;

 122:  

 123:     vector<int>::iterator iter;

 124:  

 125:     int  curTel  = -1;

 126:     for(iter = telNum.begin(); iter != telNum.end(); ++iter)

 127:     {

 128:         if(curTel == *iter){count ++;}

 129:         else

 130:         {

 131:             if(count>1)

 132:             {

 133:                 normalizedOutput(curTel ,count);

 134:                 count = 1;

 135:                 curTel = *iter;

 136:                 if(flag == 0 ) flag = 1;

 137:             }

 138:             else

 139:             {

 140:                 curTel = *iter;

 141:             }

 142:         }

 143:     }

 144:  

 145:     if(count >1)

 146:     {

 147:         normalizedOutput(curTel,count);

 148:         if(flag == 0 )flag = 1;

 149:     }

 150:  

 151:     if (flag == 0)

 152:     {

 153:         cout<<"No duplicates.";

 154:     }

 155: }

在数据量较小时,这种解法没有问题,但是一旦输入数据变多,程序的效率就会出现大问题,比如这个用这个代码在提交online judge的时候就出现了”Time Limit Exceeded”错误,最开始以为,程序运行效率的瓶颈在于这句话,众所周知,目前排序算法的效率最好也只有O(NlgN),本题最大输入数目为100000,在极端情况下效率是不行的。

sort(input_tel.begin(),input_tel.end(),sortAsc);

但是,本着实事求是的态度,我在机器上测了一下这句话的运行时间,测试方法如下(在main函数中加入时间戳):

   1: int main()

   2: {

   3:     int count;

   4:  

   5:     vector<int> input_tel;

   6:  

   7:     cin>>count;

   8:  

   9:     string curTel;

  10:     int curTelInt;

  11:     for(int i=0;i<count;++i)

  12:     {

  13:         cin>> curTel;

  14:         input_tel.push_back(cvtString2Int(curTel));

  15:  

  16:     }

  17:     clock_t start, finish;

  18:     start  = clock();

  19:  

  20:     sort(input_tel.begin(),input_tel.end(),sortAsc);

  21:  

  22:     finish = clock();

  23:  

  24:     cout<<"time eclapse: " <<start<<"/"<<finish<<"/"<<(double)(finish-start)<<"/"<<(double)(finish-start)/CLOCKS_PER_SEC <<endl;

  25:     

  26:     //showIntVector(input_tel);

  27:     showDump(input_tel);

  28:  

  29:     finish = clock();

  30:  

  31:     cout<<"time eclapse: " <<start<<"/"<<finish<<"/"<<(double)(finish-start)<<"/"<<(double)(finish-start)/CLOCKS_PER_SEC <<endl;

  32:     return 1;

  33: }

得到的结果大大出乎我的意料,我用73728个数据进行极端测试,结果发现,排序所用时间其实很短,下面是运行结果

可以看到,实际上排序只花了21毫秒,很快就完成了。

那么究竟出了什么问题?

仔细分析觉得可能是online judge把我的输入时间算在总时间里面了,这样的话cin的效率必须考虑,网上搜了一下,发现C++和G++在cin的效率上差别还蛮大的,于是编译器改成了C++,这样一来竟然直接就AC了,汗~(因为程序我是在minGW中调试的,所以submit的时候我一直选G++)。

一般提交时,对于c++程序,用G++或者C++,根据poj中FAQ的描述:

VC++中很多细节实现和C++标准不一样,因此,可以想见,VC++中cin的实现更有效率些或者cin的配置更有效率些。

有了这个想法,就在网上搜索相关资料,发现,其实在G++中也有方式能够使得cin的效率提高,只需在程序开头配置一下就好了,如下:

   1: std::ios::sync_with_stdio(false);

具体原因在探寻C++最快的读取文件的方案 中有解释,大概意思就是“对于G++,默认的时候,cin与stdin总是保持同步的,也就是说这两种方法可以混用,而不必担心文件指针混乱,同时cout和stdout也一样,两者混用不会输出顺序错乱。正因为这个兼容性的特性,导致cin有许多额外的开销,如何禁用这个特性呢?只需刚才的语句即可”。总之,VC对cin取消同步与否不敏感,前后效率相同。反过来MINGW则非常敏感,前后效率相差8倍。

一般来讲,linux程序会比window上的程序效率高一点,在用G++和C++都能AC过之后,

发现,同样的程序,时间效率上G++要高很多。这也是一个以后需要注意的问题。

程序写得略长,实际上有些小改进,比如说normlizedoutput函数可以如下改进:

void normalizedOutput(int & tel,int &count)

{

    cout<<tel/1000000<<tel/100000%10<<tel/10000%10<<"-";  

    cout<<tel/1000%10<<tel/100%10<<tel/10%10<<tel%10<<" "<<count<<endl; 

}

//或者直接写入showDump函数中,毕竟调用函数也有开销。

这么一改进之后,程序效率进一步提高,

最终程序如下:

/*author :lipan

  date: 2013.7.23

  email: areslipan@163.com

 */

 

#include <iostream>

#include <vector>

#include <iterator>

#include <string>

#include <algorithm>

using namespace std;

 

int cvtString2Int(string & str);

void normalizedOutput(int &tel,int &count);

void showDump(vector<int> & telNum);

 

bool sortAsc(const int & v1 ,const int & v2)

{

    return v1<v2;

}

 

int main()

{

    int count;

 

    vector<int> input_tel;

    std::ios::sync_with_stdio(false);

    cin>>count;

 

    string curTel;

    int curTelInt;

    for(int i=0;i<count;++i)

    {

        cin>> curTel;

        input_tel.push_back(cvtString2Int(curTel));

 

    }

    

 

    sort(input_tel.begin(),input_tel.end(),sortAsc);

 

    showDump(input_tel);

    return 1;

}

 

int cvtString2Int(string & str)

{

    int ret = 0;

    for(int i = 0; i< str.length(); ++i)

    {

        if(str[i] == '-') continue;

        

        int digit;

        if(str[i]>='0'&&str[i]<='9')

        {

            digit = str[i] - '0';

        }

        else

        {

            if (str[i] <'Z' &&str[i]>'Q')

            {

                digit = (str[i] - 'Q')/3 + 7;

            }

            else

                if(str[i]>='A' &&str[i]<'Q')

                {

                    digit = (str[i] - 'A')/3 + 2;

                }

        }

 

        ret = 10 * ret + digit;

 

    }    

 

    return ret;

}

 

/*

void normalizedOutput(int &tel,int &count)

{

    vector<int> result;

    int bitNum  = 0;

    while(tel!=0)

    {

        result.push_back(tel%10);

        tel /=10;

        bitNum ++;

    }


    int hy = 0;

    while(bitNum<7)

    {

        cout << '0';

        hy++;

        if(hy == 3)cout << '-';

        bitNum ++;

    }


    vector<int>::reverse_iterator  iter;

    for(iter = result.rbegin();iter!= result.rend();++iter)

    {

        cout<<*iter;

        hy++;

        if(hy == 3)cout<<'-';

    }


    cout<<" "<<count<<endl;


}*/

 

void normalizedOutput(int & tel,int &count)

{

    cout<<tel/1000000<<tel/100000%10<<tel/10000%10<<"-";  

    cout<<tel/1000%10<<tel/100%10<<tel/10%10<<tel%10<<" "<<count<<endl; 

}

void showDump(vector<int> & telNum)

{

    int flag = 0;

    int count = 1;

 

    vector<int>::iterator iter;

 

    int  curTel  = -1;

    for(iter = telNum.begin(); iter != telNum.end(); ++iter)

    {

        if(curTel == *iter){count ++;}

        else

        {

            if(count>1)

            {

                normalizedOutput(curTel ,count);

                count = 1;

                curTel = *iter;

                if(flag == 0 ) flag = 1;

            }

            else

            {

                curTel = *iter;

            }

        }

    }

 

    if(count >1)

    {

        normalizedOutput(curTel,count);

        if(flag == 0 )flag = 1;

    }

 

    if (flag == 0)

    {

        cout<<"No duplicates.";

    }

}

POJ-1002 解题报告的更多相关文章

  1. POJ 1001 解题报告 高精度大整数乘法模版

    题目是POJ1001 Exponentiation  虽然是小数的幂 最终还是转化为大整数的乘法 这道题要考虑的边界情况比较多 做这道题的时候,我分析了 网上的两个解题报告,发现都有错误,说明OJ对于 ...

  2. poj分类解题报告索引

    图论 图论解题报告索引 DFS poj1321 - 棋盘问题 poj1416 - Shredding Company poj2676 - Sudoku poj2488 - A Knight's Jou ...

  3. POJ 1003 解题报告

    1.问题描述: http://poj.org/problem?id=1003 2.解题思路: 最直观的的想法是看能不能够直接求出一个通项式,然后直接算就好了, 但是这样好水的样子,而且也不知道这个通项 ...

  4. POJ 1004 解题报告

    1.题目描述: http://poj.org/problem?id=1004 2.解题过程 这个题目咋一看很简单,虽然最终要解出来的确也不难,但是还是稍微有些小把戏在里面,其中最大的把戏就是float ...

  5. POJ 1005 解题报告

    1.题目描述   2.解题思路 好吧,这是个水题,我的目的暂时是把poj第一页刷之,所以水题也写写吧,这个题简单数学常识而已,给定坐标(x,y),易知当圆心为(0,0)时,半圆面积为0.5*PI*(x ...

  6. POJ 3414 解题报告!

    原题: Pots Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 13227 Accepted: 5550 Special Jud ...

  7. POJ 2411 解题报告

    传送门:http://poj.org/problem?id=2411 题目简述 有一个\(W\)行\(H\)列的广场,需要用\(1*2\)小砖铺满,小砖之间互相不能重叠,问 有多少种不同的铺法? 输入 ...

  8. PAT (Advanced Level) Practise 1002 解题报告

    GitHub markdownPDF 问题描述 解题思路 代码 提交记录 问题描述 A+B for Polynomials (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 ...

  9. 广大暑假训练1 E题 Paid Roads(poj 3411) 解题报告

    题目链接:http://poj.org/problem?id=3411 题目意思:N个city 由 m 条路连接,对于一条路(假设连接Cityia和 Cityb),如果从Citya 去 Cityb的途 ...

  10. POJ旅行商问题——解题报告

    旅行商问题 总时间限制: 1000ms 内存限制: 65536kB 描述 某国家有n(1<=n<=10)座城市,给定任意两座城市间距离(不超过1000的非负整数).一个旅行商人希望访问每座 ...

随机推荐

  1. HTTP响应消息code解释

    常见HTTP状态(304,200等) 在网站建设的实际应用中,容易出现很多小小的失误,就像mysql当初优化不到位,影响整体网站的浏览效果一样,其实,网站的常规http状态码的表现也是一样,Googl ...

  2. centos下安装JDK8的方法

    判断是否安装 首先,我们得判断机子上是不是安装了jdk,好多人推荐使用java -version命令.我的计算机上使用java -version命令,内容如下: java version " ...

  3. laravel加载javascript库

    一篇文章: Generating a Link to a Javascript File Problem You want your Blade template to load an externa ...

  4. sql 随笔 2015-06-30

    清除多余字符 --清除多余字符 --' --char(9) 水平制表符 --char(10)换行键 --char(13)回车键 REPLACE( REPLACE( REPLACE(REPLACE([P ...

  5. hive学习笔记——表的基本的操作

    1.hive的数据加载方式 1.1.load data 这中方式一般用于初始化的时候 load data [local] inpath '...' [overwrite] into table t1 ...

  6. 在XML里的XSD和DTD以及standalone的使用3----具体使用详解

    本人亲自写的一个简单的测试例子 1.xsd定义 <?xml version="1.0" encoding="utf-8"?><xs:schem ...

  7. Spring学习8-Spring事务管理

      http://blog.sina.com.cn/s/blog_7ffb8dd501014e0f.html   Spring学习8-Spring事务管理(注解式声明事务管理) 标签: spring注 ...

  8. 进程控制的一些api

    转自:http://blog.chinaunix.net/uid-26833883-id-3222794.html 1.fork() ,vfork() 创建进程 2‘ exec()类 在进程中执行其他 ...

  9. powerScript脚本

    一.powerScript的语法 1.0变量的命名及使用 powerscript的标识符(变量名称)必须以字母或下划线开头,其它的字符可以是下划线(_).短横线(-).美元符号($).号码符号(#) ...

  10. [swustoj 771] 奶牛农场

    奶牛农场 Description 将军有一个用栅栏围成的矩形农场和一只奶牛,在农场的一个角落放有一只矩形的箱子,有一天将军要出门,他就把奶牛用一根绳子套牢,然后将绳子的另一端绑到了那个箱子不靠栅栏的角 ...