(一)体面
人人公司是一家极为鼓励极客精神的公司,当有重要的项目需要上线但又时间太紧,甚至需要当天上线的时候,往往会挂起海盗旗开启电子日期显示,让大家可以在对时间有更明确的感知的情况下,同心协力搞定重要的项目。海盗旗下方的电子屏显示的日期形式为 YYYYMMDD (年份占 4 位、月份占 2 位、天数占 2 位)。
日期电子屏幕上每个数字对应的显示如下图:
从上图可以得知每个数字对应的笔画数,比如 2 的笔画数是 5,8 的笔画数是 7,等等。人人员工小明看到了项目的启动日期 d,但是项目的结束日期没看清楚,只知道电子屏幕上项目结束日期所需的笔画数为 m,你能帮小明算出来项目执行所用的时间天数么?
输入格式
输入数据有多组。第一行输入一个整数 T (1 ≤ T ≤ 20),表示一共有 T 组数据。
接下来每组数据 2 行,共 T * 2 行。每组第一行输入一个长度为 8 的仅包含数字的字符串 d,表示项目的启动日期,形式为 YYYYMMDD。每组第二行输入一个非负整数 m (0 ≤ m ≤ 100),表示电子屏幕上项目结束日期所需的笔画数。输入日期保证合法。
输出格式
一共输出 T 行,每行一个整数,表示该组数据对应的项目执行所用的时间天数。如果最近的符合要求的结束日期超过 2999 年 12 月 31 日或无解则输出 -1,否则输出符合要求的最小的解。
样例1
输入:
2 20150718 30 29991231 38
输出:
85 -1
(二)参考源码
java实现是我自己写的,另推荐一个C++实现,代码非常简洁。http://www.cnblogs.com/Tinamei/p/4658133.html
1 import java.io.BufferedReader; 2 import java.io.InputStreamReader; 3 import java.text.DateFormat; 4 import java.text.ParseException; 5 import java.text.SimpleDateFormat; 6 import java.util.ArrayList; 7 import java.util.Arrays; 8 import java.util.Calendar; 9 import java.util.HashMap; 10 import java.util.LinkedHashMap; 11 import java.util.Map; 12 13 public class Main { 14 private static BufferedReader reader = new BufferedReader( 15 new InputStreamReader(System.in)); 16 // 每个数字的笔画数 17 private static Map<String, Integer> numberMap = new HashMap<String, Integer>(); 18 // 每个月份的笔画数,例如2月是‘0’和‘2’的笔画数之和 19 private static Map<String, Integer> monthMap = new HashMap<String, Integer>(); 20 // 每天的笔画数,例如31是‘3’和‘1’的笔画数之和 21 private static Map<String, Integer> dayMap = new HashMap<String, Integer>(); 22 // 每天有多少个笔画,例如11月12日,1112=11 23 private static Map<String, Integer> dateMap = new LinkedHashMap<String, Integer>(); 24 private static String monthArray[] = { "01", "02", "03", "04", "05", "06", 25 "07", "08", "09", "10", "11", "12" }; 26 // 平年每个月有多少天,例如1月:01=31 27 private static Map<String, Integer> daysEachMonthMap = new LinkedHashMap<String, Integer>(); 28 // key:笔画数 value:日期列表,日期自小到大.例如:11=[1112, 1113, 1115, 1121, 1211] 29 private static Map<Integer, ArrayList<String>> countDateListMap = new HashMap<Integer, ArrayList<String>>(); 30 // key:笔画数 value:日期数组,日期自小到大.例如:11=[1112, 1113, 1115, 1121, 1211] 31 private static Map<Integer, String[]> countDateArrayMap = new HashMap<Integer, String[]>(); 32 // 2月29有多少画 33 private static final int COUNT_0229 = 6 + 5 + 5 + 6; 34 // 2月29的字符串表示 35 private static final String STRING_0229 = "0229"; 36 // 换行符 37 private static final String LINE_SEPARATOR = System 38 .getProperty("line.separator"); 39 private static final DateFormat dateFormat = new SimpleDateFormat( 40 "yyyyMMdd"); 41 // 每个月有多少天 42 private static int[] daysEachMonthArray = { 0, 31, 28, 31, 30, 31, 30, 31, 43 31, 30, 31, 30, 31 }; 44 static { 45 daysEachMonthMap.put("01", 31); 46 daysEachMonthMap.put("02", 28); 47 daysEachMonthMap.put("03", 31); 48 daysEachMonthMap.put("04", 30); 49 daysEachMonthMap.put("05", 31); 50 daysEachMonthMap.put("06", 30); 51 52 daysEachMonthMap.put("07", 31); 53 daysEachMonthMap.put("08", 31); 54 daysEachMonthMap.put("09", 30); 55 daysEachMonthMap.put("10", 31); 56 daysEachMonthMap.put("11", 30); 57 daysEachMonthMap.put("12", 31); 58 59 numberMap.put("0", 6); 60 numberMap.put("1", 2); 61 numberMap.put("2", 5); 62 numberMap.put("3", 5); 63 numberMap.put("4", 4); 64 numberMap.put("5", 5); 65 numberMap.put("6", 6); 66 numberMap.put("7", 3); 67 numberMap.put("8", 7); 68 numberMap.put("9", 6); 69 70 for (int i = 0; i < monthArray.length; i++) { 71 monthMap.put( 72 monthArray[i], 73 numberMap.get(String.valueOf(monthArray[i].charAt(0))) 74 + numberMap.get(String.valueOf(monthArray[i] 75 .charAt(1)))); 76 } 77 for (int i = 1; i <= 31; i++) { 78 String dayKey = null; 79 if (i < 10) { 80 dayKey = "0" + i; 81 } else { 82 dayKey = String.valueOf(i); 83 } 84 dayMap.put(dayKey, numberMap.get(String.valueOf(dayKey.charAt(0))) 85 + numberMap.get(String.valueOf(dayKey.charAt(1)))); 86 } 87 for (Map.Entry<String, Integer> entry : daysEachMonthMap.entrySet()) { 88 for (int i = 0; i < entry.getValue(); i++) { 89 String dayKey = null; 90 if (i < 9) { 91 dayKey = "0" + (i + 1); 92 } else { 93 dayKey = String.valueOf(i + 1); 94 } 95 dateMap.put(entry.getKey() + dayKey, 96 monthMap.get(entry.getKey()) + dayMap.get(dayKey)); 97 } 98 } 99 for (Map.Entry<String, Integer> entry : dateMap.entrySet()) { 100 if (!countDateListMap.containsKey(entry.getValue())) { 101 countDateListMap.put(entry.getValue(), new ArrayList<String>()); 102 } 103 countDateListMap.get(entry.getValue()).add(entry.getKey()); 104 } 105 for (Map.Entry<Integer, ArrayList<String>> entry : countDateListMap 106 .entrySet()) { 107 countDateArrayMap.put(entry.getKey(), 108 entry.getValue().toArray(new String[0])); 109 } 110 } 111 112 private static int readInt() throws Exception { 113 return Integer.parseInt(reader.readLine()); 114 } 115 116 /** 117 * 118 * @param count 119 * 笔画数 120 * @param beginDate 121 * @return 大于等于beginDate,笔画数为count的最小日期;如果找不到,返回null 122 */ 123 private static String getDate(int count, String beginDate) { 124 String[] dateArray = countDateArrayMap.get(count); 125 if (null == dateArray) { 126 return null; 127 } 128 if ("0101".equals(beginDate)) { 129 return dateArray[0]; 130 } else { 131 // 二分法查找 132 int index = Arrays.binarySearch(dateArray, beginDate); 133 if (index >= 0) { 134 return beginDate; 135 } else if (-(index + 1) == dateArray.length) { 136 return null; 137 } else { 138 return dateArray[-(index + 1)]; 139 } 140 } 141 } 142 143 /** 144 * 145 * @return year的笔画数 146 */ 147 private static int getYearCount(String year) { 148 return numberMap.get(String.valueOf(year.charAt(0))) 149 + numberMap.get(String.valueOf(year.charAt(1))) 150 + numberMap.get(String.valueOf(year.charAt(2))) 151 + numberMap.get(String.valueOf(year.charAt(3))); 152 } 153 154 /** 155 * 判断某年是否有2月29这天 156 */ 157 private static boolean has0229(int year) { 158 if (year % 100 == 0) { 159 return year % 400 == 0; 160 } else { 161 return year % 4 == 0; 162 } 163 } 164 165 /** 166 * 计算endDate和beginDate之间的天数,仅支持同一年的日期比较 167 */ 168 @Deprecated 169 private static int getDays(String beginDate, String endDate) { 170 try { 171 Calendar begin = Calendar.getInstance(); 172 begin.setTime(dateFormat.parse(beginDate)); 173 Calendar end = Calendar.getInstance(); 174 end.setTime(dateFormat.parse(endDate)); 175 return end.get(Calendar.DAY_OF_YEAR) 176 - begin.get(Calendar.DAY_OF_YEAR); 177 } catch (ParseException e) { 178 throw new RuntimeException(e); 179 } 180 } 181 182 /** 183 * 考虑从1582年才开始现代闰年计算方式,对于本题,该方法仅适用于1582年以后的日期 184 */ 185 @Deprecated 186 private static int getDaysBetween(String beginDate, String endDate) { 187 try { 188 long begin = dateFormat.parse(beginDate).getTime(); 189 long end = dateFormat.parse(endDate).getTime(); 190 return (int) ((end - begin) / (24 * 60 * 60 * 1000)); 191 } catch (ParseException e) { 192 throw new RuntimeException(e); 193 } 194 } 195 196 private static int getDaysBetween2(String beginDate, String endDate) { 197 int result = 0; 198 int beginDay = Integer.parseInt(beginDate.substring(6)); 199 int beginMounth = Integer.parseInt(beginDate.substring(4, 6)); 200 int beginyear = Integer.parseInt(beginDate.substring(0, 4)); 201 202 int endDay = Integer.parseInt(endDate.substring(6)); 203 int endMounth = Integer.parseInt(endDate.substring(4, 6)); 204 int endyear = Integer.parseInt(endDate.substring(0, 4)); 205 206 while (true) { 207 if (endyear == beginyear && endMounth == beginMounth 208 && endDay == beginDay) { 209 break; 210 } 211 if (has0229(beginyear)) { 212 daysEachMonthArray[2] = 29; 213 } else { 214 daysEachMonthArray[2] = 28; 215 } 216 beginDay++; 217 if (beginDay > daysEachMonthArray[beginMounth]) { 218 beginDay = 1; 219 beginMounth++; 220 if (beginMounth > 12) { 221 beginMounth = 1; 222 beginyear++; 223 } 224 } 225 result++; 226 } 227 return result; 228 } 229 230 /** 231 * 计算给定日期的笔画数,仅用于测试 232 */ 233 private static int getCount(String date) { 234 int result = 0; 235 for (int i = 0; i < date.length(); i++) { 236 result += numberMap.get(String.valueOf(date.charAt(i))); 237 } 238 return result; 239 } 240 241 /** 242 * 对于不满4位的年份,前面用0补齐 243 */ 244 private static String getYear(int year) { 245 StringBuilder builder = new StringBuilder(); 246 builder.append(year); 247 while (builder.length() < 4) { 248 builder.insert(0, "0"); 249 } 250 return builder.toString(); 251 } 252 253 public static void main(String[] args) throws Exception { 254 255 int testCount = Main.readInt(); 256 // 存放输出结果 257 StringBuilder builder = new StringBuilder(); 258 for (int i = 0; i < testCount; i++) { 259 // 对于本组测试数据,是否已将结果存放到builder 260 boolean found = false; 261 String yearDate = reader.readLine(); 262 int count = readInt(); 263 String year = yearDate.substring(0, 4); 264 int yearInt = Integer.parseInt(year); 265 // 若果输入年份就大于或等于3000,直接输出-1 266 if (yearInt >= 3000) { 267 builder.append(-1).append(LINE_SEPARATOR); 268 found = true; 269 continue; 270 } 271 // count 最大为56,此时日期是“08880808” 272 // count 最小是16,此时日期是“11111111” 273 if (count > 56 || count < 16) { 274 builder.append(-1).append(LINE_SEPARATOR); 275 found = true; 276 continue; 277 } 278 String date = yearDate.substring(4); 279 int dateCount = count - getYearCount(year); 280 String expectedDate = getDate(dateCount, date); 281 if (null != expectedDate) { 282 if (dateCount == COUNT_0229 283 && expectedDate.compareTo(STRING_0229) > 0 284 && STRING_0229.compareTo(date) >= 0 && has0229(yearInt)) { 285 builder.append( 286 getDaysBetween2(yearDate, year + STRING_0229)) 287 .append(LINE_SEPARATOR); 288 found = true; 289 continue; 290 } else { 291 builder.append( 292 getDaysBetween2(yearDate, year + expectedDate)) 293 .append(LINE_SEPARATOR); 294 found = true; 295 continue; 296 } 297 } else { 298 if (dateCount == COUNT_0229 && STRING_0229.compareTo(date) >= 0 299 && has0229(yearInt)) { 300 builder.append( 301 getDaysBetween2(yearDate, year + STRING_0229)) 302 .append(LINE_SEPARATOR); 303 found = true; 304 continue; 305 } else { 306 // no thing to do 307 } 308 } 309 310 for (int j = yearInt + 1; j < 3000; j++) { 311 dateCount = count - getYearCount(getYear(j)); 312 // count 最大为26,此时日期是“0808” 313 // count 最小是8,此时日期是“1111” 314 if (dateCount > 26 || dateCount < 8) { 315 continue; 316 } 317 expectedDate = getDate(dateCount, "0101"); 318 if (null != expectedDate) { 319 if (dateCount == COUNT_0229 320 && expectedDate.compareTo(STRING_0229) > 0 321 && has0229(j)) { 322 builder.append( 323 getDaysBetween2(yearDate, getYear(j) 324 + STRING_0229)).append(LINE_SEPARATOR); 325 found = true; 326 break; 327 } else { 328 builder.append( 329 getDaysBetween2(yearDate, getYear(j) 330 + expectedDate)).append(LINE_SEPARATOR); 331 found = true; 332 break; 333 } 334 } else { 335 if (dateCount == COUNT_0229 && has0229(j)) { 336 builder.append( 337 getDaysBetween2(yearDate, getYear(j) 338 + STRING_0229)).append(LINE_SEPARATOR); 339 found = true; 340 break; 341 } else { 342 continue; 343 } 344 } 345 } 346 if (!found) { 347 builder.append(-1).append(LINE_SEPARATOR); 348 } 349 } 350 System.out.println(builder.toString()); 351 } 352 }
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 typedef long long LL; 7 int year[3000], month2[13], day[40]; 8 int s[10] = {6, 2, 5, 5, 4, 5, 6, 3, 7, 6}; // 存第几个数需要几笔画数 9 int month1[2][13] = {0,31,28,31,30,31,30,31,31,30,31,30,31,0,31,29,31,30,31,30,31,31,30,31,30,31}; // month[0]存不是闰年当前月份天数 10 void init () 11 { 12 for (int i=0; i<40; i++) 13 day[i] = s[i%10] + s[i/10]; // 第几天所需笔画数,第一天是0和1所需笔画数之和 14 for (int i=0; i<13; i++) 15 month2[i] = s[i%10] + s[i/10]; // 第几月所需笔画数,12月是1和2所需笔画数之和 16 memset(year, 0, sizeof(year)); 17 for (int i=0; i<3000; i++) 18 { 19 int m = i; 20 for (int j=0; j<4; j++) 21 { 22 year[i] += s[m%10]; // 第几年所需笔画数2015年是数字2,0,1,5所需笔画数之和 23 m /= 10; 24 } 25 } 26 } 27 int main () 28 { 29 init(); 30 int t, y, m, d, num, ans; 31 32 scanf ("%d", &t); 33 while (t --) 34 { 35 int flag = 0; 36 ans = 0; 37 scanf ("%4d%2d%2d", &y, &m, &d); 38 39 if (y%400==0 || (y%4==0)&&(y%100!=0)) // 是否闰年 40 flag = 1; 41 scanf ("%d", &num); 42 while (true) 43 { 44 int nu = year[y] + month2[m] + day[d]; // 当前所到日期所需笔画数 45 if (nu == num) // 相等结束while 46 break; 47 if (y==2999 && m==12 && d==31) 48 { 49 ans = -1; 50 break; 51 } 52 d ++; // 每次d+1,ans+1,当加到日期笔画数和输入相同时结束while 53 ans ++; 54 if (month1[flag][m] < d) 55 { 56 d -= month1[flag][m]; // 月份< d时,天数从0开始下月计算,月份m+1 57 m ++; 58 } 59 if (m > 12) // 月份大于12,下一年开始计 60 { 61 m -= 12; 62 y ++; 63 if (y%400==0 || (y%4==0)&&(y%100!=0)) 64 flag = 1; 65 else 66 flag = 0; 67 } 68 } 69 printf ("%d\n", ans); // 输出天数 70 } 71 return 0; 72 }