20130323编程马拉松被虐第一题
如题,参加腾讯的编程马拉松比赛,由于好久没有码C++代码,错误百出,2个小时竟没有完成第一题!(一共有5道)
痛定思痛,开博搞起。
坚持学习C++,每天进步一点点!
第一题题目是(经简化,出题人太爱扯淡,就不耽误大家时间了):
小Q和HR相约在腾讯第二届编程马拉松大赛进行到第5天的时候(即2013年3月24日),一起“向前穿越D天,然后开启幸福新生活”。
其勇气可谓令人赞叹,但可怜的小Q却总是备受折磨——小Q理解的”向前穿越”是朝着未来的方向,而女友HR理解的“向前穿越”却是朝着古代的方向!
假设已知现在的日期和穿越的天数D,你能计算出小Q和女友各自到达的年代吗?
Input
输入首先包含一个整数N,表示有N组测试用例;
接下来N行是N组数据,每一行包含一个正整数D(D<=10,0000),D表示向前穿越的天数。
Output
请计算并输出小Q和女友分别到达的日期,日期格式为YYYY/MM/DD,两个日期中间用一个空格隔开,每组数据占一行,具体输出格式请参见样例。
Sample Input
2
6
30
Sample Output
2013/03/30 2013/03/18
2013/04/23 2013/02/22
我的解法是:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <iomanip> 3 using namespace std; 4 bool IsLeapYear(int x) 5 { 6 if( x/100*100 == x ) 7 { 8 if( x/400*400 == x ) 9 { 10 return true; 11 } 12 else 13 { 14 return false; 15 } 16 } 17 else 18 { 19 if( x/4*4 == x ) 20 { 21 return true; 22 } 23 else 24 { 25 return false; 26 } 27 } 28 } 29 30 int main() 31 { 32 int D[100]={}; 33 int N=0; 34 int year=2013, 35 month=3, 36 day=24, 37 y=2013, 38 m=3, 39 d=24, 40 delta=0, 41 days=0; 42 int monthDay[12]={31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 43 44 cin>>N; 45 46 for(int i=1;i<N+1;i++) 47 { 48 cin>>D[i]; 49 } 50 51 for(int i=1;i<N+1;i++) 52 { 53 54 //xiao q 55 delta=D[i]; 56 y=year; 57 m=month; 58 d=day; 59 y=year+delta/365; 60 delta=delta-delta/365*365; 61 if( delta==0 ) 62 { 63 y--; 64 delta=365; 65 } 66 for(int yit=year; yit<y+1; yit++) 67 { 68 if( IsLeapYear(yit) ) 69 { 70 delta--; 71 } 72 } 73 74 if( IsLeapYear(y) ) 75 { 76 monthDay[2-1]=29; 77 } 78 while(delta>0) 79 { 80 if( delta>monthDay[m-1] ) 81 { 82 delta=delta-monthDay[m-1]; 83 84 m= ++m==13?12:m; 85 y++; 86 if( IsLeapYear(y) ) 87 { 88 monthDay[2-1]=29; 89 } 90 else 91 { 92 monthDay[2-1]=28; 93 } 94 95 } 96 else 97 { 98 if( delta>monthDay[m-1]-d) 99 { 100 d=delta-(monthDay[m-1]-d); 101 m= ++m==13?12:m; 102 } 103 else 104 { 105 d=d+delta; 106 } 107 delta=0; 108 } 109 } 110 cout<<setfill('0')<<setw(4)<<y<<"/"<<setw(2)<<m<<"/"<<setw(2)<<d<<" "; 111 112 //hr 113 delta=D[i]; 114 y=year; 115 m=month; 116 d=day; 117 y=year-delta/365; 118 delta=delta-delta/365*365; 119 if( delta==0 ) 120 { 121 y++; 122 delta=365; 123 } 124 for(int yit=year; yit>y; yit--) 125 { 126 if( IsLeapYear(yit) ) 127 { 128 delta--; 129 } 130 } 131 if( IsLeapYear(y) ) 132 { 133 monthDay[2-1]=29; 134 } 135 while(delta>0) 136 { 137 if( m>1 ) 138 { 139 days=monthDay[(m-1)-1]; 140 } 141 else 142 { 143 days=monthDay[12-1]; 144 } 145 if( delta>days ) 146 { 147 delta=delta-days; 148 149 m= --m==0?12:m; 150 y--; 151 if( IsLeapYear(y) ) 152 { 153 monthDay[2-1]=29; 154 } 155 else 156 { 157 monthDay[2-1]=28; 158 } 159 160 } 161 else 162 { 163 if( delta>d ) 164 { 165 d=days-(delta-d); 166 m= --m==0?12:m; 167 } 168 else 169 { 170 d=d-delta; 171 } 172 delta=0; 173 } 174 } 175 cout<<setfill('0')<<setw(4)<<y<<"/"<<setw(2)<<m<<"/"<<setw(2)<<d<<endl; 176 177 } 178 return 0; 179 }
算法先抛开不谈,我们先谈谈编写过程中遇到的种种知识遗忘点:
1.include<> 声明头文件,有的时候写iostream,有的时候写iostream.h,有什么区别呢?
我搜索这个问题,找到一篇解释较为详尽的博客:http://www.blogjava.net/hijackwust/archive/2008/06/20/209529.html
简要解释如下:include<iostream.h>是C风格的,include<iostream>是C++风格的。前者会将标准库中的函数作为全局函数,而后者则是将标准库中的函数放入名字空间std中。名字空间namespace是C++标准委员会在1998年标准化之后引入的概念,这是因为:标准库涵盖范围很广,里面的类、函数很多,这就可能会与第三方提供的程序库中的类或函数发生名字冲突,有了名字空间,标准库中的东西就都放在了namespace std中了。iostream.h是98年之前的C++标准,应该被淘汰,只是因为编译器厂商利益才苟延残喘,严格说应是编译错误的。其他有一些*.h的头文件保留是为了对C兼容。
另外,后续程序为了书写方便,经常会加上using namespace std; 这样后面用标准库的函数就可以直接写了。
2.C++输出流的格式控制,如何将2显示为02呢?
又是基础知识,参考博客为:http://blog.csdn.net/virtualdesk/article/details/5355793
有两种方式控制输出格式:一是用控制符,二是用流对象的成员函数。下面给个控制符的示例。以小数形式,保留三位小数输出:
cout<<setprecision(3)<<setiosflags(ios::fixed)<<3.1415926<<endl;
3.求模是什么符号?(我一直用坑爹的整数除法乘法 x/400*400)简单的判断语句可以不用if...else...而更简洁吗?各运算符优先级怎样的,以便减少圆括号?
这是一大波C++特殊符号问题,参考博客为:http://blog.csdn.net/shencaifeixia1/article/details/7831134
第二个问题的答案是:条件运算符 ? :
我后续改进也用到了它,如
m= --m==0?12:m;
这里还要注意一点是关于自减运算符的,--m是先自减再做其他运算,而m--是先做其他运算再自减。前者是正确的写法,因为--是右结合的单目运算符,而后者是通过运算符重载而加入C++的。就像博客里说的:“另外在C语言里 没有前置后置之分 因为++ -- 是右结合所以 右侧优先运算 表现为 "后置优先级比较高" 的假象 前置和后置的区分是因为运算符重载而后加入C++的。”
先说这么多,该睡了,明天继续。