POJ-1002 解题报告
1.题目描述
2.解题过程
按部就班来解题的话,这个题目很容易写出来,这是我的第一个版本的代码,思路是读入一行电话字符串,均转化为整型数字存入vector结构,然后进行排序,顺序统计即可发现重复的电话号码及次数。
1: /*author :lipan2: date: 2013.7.233: email: areslipan@163.com4: */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: else67: {68: if (str[i] <'Z' &&str[i]>'Q')69: {70: digit = (str[i] - 'Q')/3 + 7;71: }72: else73: 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: else130: {131: if(count>1)132: {133: normalizedOutput(curTel ,count);134: count = 1;135: curTel = *iter;136: if(flag == 0 ) flag = 1;137: }138: else139: {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 :lipandate: 2013.7.23email: 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;}elseif(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 解题报告的更多相关文章
- POJ 1001 解题报告 高精度大整数乘法模版
题目是POJ1001 Exponentiation 虽然是小数的幂 最终还是转化为大整数的乘法 这道题要考虑的边界情况比较多 做这道题的时候,我分析了 网上的两个解题报告,发现都有错误,说明OJ对于 ...
- poj分类解题报告索引
图论 图论解题报告索引 DFS poj1321 - 棋盘问题 poj1416 - Shredding Company poj2676 - Sudoku poj2488 - A Knight's Jou ...
- POJ 1003 解题报告
1.问题描述: http://poj.org/problem?id=1003 2.解题思路: 最直观的的想法是看能不能够直接求出一个通项式,然后直接算就好了, 但是这样好水的样子,而且也不知道这个通项 ...
- POJ 1004 解题报告
1.题目描述: http://poj.org/problem?id=1004 2.解题过程 这个题目咋一看很简单,虽然最终要解出来的确也不难,但是还是稍微有些小把戏在里面,其中最大的把戏就是float ...
- POJ 1005 解题报告
1.题目描述 2.解题思路 好吧,这是个水题,我的目的暂时是把poj第一页刷之,所以水题也写写吧,这个题简单数学常识而已,给定坐标(x,y),易知当圆心为(0,0)时,半圆面积为0.5*PI*(x ...
- POJ 3414 解题报告!
原题: Pots Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 13227 Accepted: 5550 Special Jud ...
- POJ 2411 解题报告
传送门:http://poj.org/problem?id=2411 题目简述 有一个\(W\)行\(H\)列的广场,需要用\(1*2\)小砖铺满,小砖之间互相不能重叠,问 有多少种不同的铺法? 输入 ...
- PAT (Advanced Level) Practise 1002 解题报告
GitHub markdownPDF 问题描述 解题思路 代码 提交记录 问题描述 A+B for Polynomials (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 ...
- 广大暑假训练1 E题 Paid Roads(poj 3411) 解题报告
题目链接:http://poj.org/problem?id=3411 题目意思:N个city 由 m 条路连接,对于一条路(假设连接Cityia和 Cityb),如果从Citya 去 Cityb的途 ...
- POJ旅行商问题——解题报告
旅行商问题 总时间限制: 1000ms 内存限制: 65536kB 描述 某国家有n(1<=n<=10)座城市,给定任意两座城市间距离(不超过1000的非负整数).一个旅行商人希望访问每座 ...
随机推荐
- android MD5
public static String MD5(String str) { MessageDigest md5 = null; try { md5 = MessageDigest.getInstan ...
- servlet会话技术:Cookie
什么是会话会话可以简单理解为:用户开一个浏览器访问某个网站,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话.会话过程中需要解决的一些问题每个用户在使用浏览器与服务器进 ...
- Junit使用教程(四)
一.会用Spring测试套件的好处 在开发基于Spring的应用时,如果你还直接使用Junit进行单元测试,那你就错过了Spring为我们所提供的饕餮大餐了.使用Junit直接进行单元测试有以下四大不 ...
- Generic Data Access Layer泛型的数据访问层
http://www.codeproject.com/Articles/630277/Generic-Data-Access-Layer-GDA-Part-I http://www.codeproje ...
- [58 Argo]让argo跑起来
接上一章,使用命令mvn jetty:run启动Argo,进入localhost的页面: 58在这里给了几种常见的访问和传值方法的示例,当点击到第三条<区分queryString和form参数& ...
- svn is already under version control问题解决
svn ci 时出现 xx is already under version control,然后无法提交,出现这个问题的原因是你所提交的文件或目录是其他SVN的东西,即下面有.svn的目录,需要先把 ...
- 函数buf_page_hash_get_low
/******************************************************************//** Returns the control block of ...
- jquery 字符串转json
这里考虑的都是服务器返回JSON形式的字符串的形式 代码如下: var data=" { root: [ {name:'1',value:'0'}, {name:'6101',value:' ...
- 用Java Servlets代替CGI
从网络的早期阶段开始,人们就希望他们的网络服务器不仅能够显示静态文档,通用网关接口(CGI) 扩展了服务器的能力,但其代价是增加了额外的处理进程.FastCGI则把外部CGI 处理进程同网络服务器更紧 ...
- AJAX在GBK编码页面中传中文参数乱码的问题
---恢复内容开始--- 页面编码是GBK的情况下传递中文有乱码,解决方法如下: 在ajax传递前用若是Array,JSON,等其它对象,可用JSON.stringfy字符串序列化后,赋值给ajax传 ...



