2013腾讯编程马拉松初赛(3月24日)
1 题目一 小Q系列故事——最佳裁判
这道题就是找最大值和最小值的题目,学过c的应该都没问题的。
2 题目二 小明系列问题——小明序列
这道题目是最长上升子序列的一种变形吧,就是子序列中相邻数的下标之差必须大于d(开始看错题目,以为是相邻数之差大于d,结果wa了好多次,最后看了别人的discuss才恍然大悟啊!)。用二分查找在子序列中要替换的位置,注意在处理第i个数时,才更新第i-d个数在子序列中的位置就行了,而不是原来更新第i个数在子序列中的位置。
1 #include <stdio.h> 2 3 #define INIFITE 100000000 4 int n, d ; 5 int data[100005]; 6 int stack[100005]; 7 int dp[100005]; 8 int top; 9 10 int find(int x, int len) 11 { 12 int left = 0, right = len, mid; 13 14 while (left <= right) 15 { 16 mid = (left + right) / 2; 17 if (stack[mid] < x) 18 left = mid + 1; 19 else 20 right = mid - 1; 21 } 22 return left; 23 } 24 int main(void) 25 { 26 int i, temp, ans; 27 28 while (scanf("%d%d", &n, &d) != EOF) 29 { 30 for (i = 0; i < n; i ++) 31 scanf("%d", &data[i]); 32 for (i = 0; i < d && i < n; i ++) 33 dp[i] = 0; 34 for (i = 0; i < n; i ++) 35 stack[i] = INIFITE; 36 for (i = d; i < n; i ++) 37 { 38 temp = find(data[i], i); 39 dp[i] = temp; 40 if (stack[dp[i - d]] > data[i - d]) 41 stack[dp[i - d]] = data[i - d]; 42 //printf("%d, %d\n", i, dp[i]); 43 } 44 ans = 0; 45 for (i = 0; i < n; i ++) 46 if (dp[i] > ans) 47 ans = dp[i]; 48 printf("%d\n", ans + 1); 49 } 50 return 0; 51 }
3 题目三 湫湫系列故事——过年回家
这道题目初看没什么头绪,后来认真分析发现其实就是一道求单源最短路径的问题,只是要求两次,一次是坐卧铺的,一次是做硬座的,求最小不适应度。
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 5 #define INFINITE 4000000 6 int q, n, t, d1, d2, a, b; 7 int position[201][201]; 8 int k[205][205][2]; 9 int path[10005]; 10 char strData[10005]; 11 int ans[205]; 12 13 14 int get_path() 15 { 16 int len, i, count, pathLen; 17 char node[5]; 18 19 len = strlen(strData); 20 i = 0; 21 count = 0; 22 pathLen = 0; 23 while (i < len) 24 { 25 if ('+' == strData[i]) 26 { 27 node[count] = 0; 28 path[pathLen ++] = atoi(node); 29 count = 0; 30 } 31 else 32 node[count ++] = strData[i]; 33 i ++; 34 } 35 node[count] = 0; 36 path[pathLen ++] = atoi(node); 37 return pathLen; 38 } 39 void dijkstra(int s) 40 { 41 int flag[205], i, j, min, k; 42 43 for (i = 1; i <= n; i ++) 44 { 45 flag[i] = 0; 46 ans[i] = position[s][i]; 47 } 48 flag[s] = 1; 49 ans[i] = 0; 50 for (i = 1; i < n; i ++) 51 { 52 min = INFINITE; 53 for (j = 1; j <= n; j ++) 54 if (!flag[j] && ans[j] < min) 55 { 56 min = ans[j]; 57 k = j; 58 } 59 if (INFINITE == min) 60 break; 61 flag[k] = 1; 62 for (j = 1; j <= n; j ++) 63 if (!flag[j] && ans[k] + position[k][j] < ans[j]) 64 ans[j] = ans[k] + position[k][j]; 65 } 66 } 67 int main(void) 68 { 69 int i, j, temp, len, ii; 70 71 scanf("%d", &q); 72 for (i = 0; i < q; i ++) 73 { 74 memset(k, -1, sizeof(k)); 75 scanf("%d%d", &n, &t); 76 for (j = 0; j < t; j ++) 77 { 78 scanf("%s%d", strData, &temp); 79 len = get_path(); 80 for (ii = 0; ii < len - 1; ii ++) 81 k[path[ii]][path[ii + 1]][temp] = 1; 82 } 83 scanf("%d%d", &d1, &d2); 84 scanf("%d%d", &a, &b); 85 86 //坐卧铺 87 for (ii = 1; ii <= n; ii ++) 88 for (j = 1; j <= n; j ++) 89 if (1 == k[ii][j][1]) 90 position[ii][j] = d2; 91 else 92 position[ii][j] = INFINITE; 93 dijkstra(a); 94 temp = ans[b]; 95 memset(position, INFINITE, sizeof(position)); 96 //坐卧铺 97 for (ii = 1; ii <= n; ii ++) 98 for (j = 1; j <= n; j ++) 99 if (1 == k[ii][j][0] || 1 == k[ii][j][1]) 100 position[ii][j] = d1; 101 else 102 position[ii][j] = INFINITE; 103 dijkstra(a); 104 if (temp > ans[b]) 105 temp = ans[b]; 106 if (INFINITE == temp) 107 printf("-1\n"); 108 else 109 printf("%d\n", temp); 110 } 111 return 0; 112 }
4 题目四 威威猫系列故事——过生日
这道题只要满足n + p >= m,n表示切前的多边形的边数,p表示切的刀数,m表示要切成的多边形的边数。但由于n,m,p要满足下列条件:
3 <= n <= 10^100
0 < m <= 10^100
0 <= p <= 10^100
所以这道题实际是一个大整数加减法的问题。
1 #include <stdio.h> 2 #include <string.h> 3 4 char n[102], m[102], p[102]; 5 int ni[103], mi[103], pi[103]; 6 7 int main(void) 8 { 9 int lenn, lenm, lenp, i, maxlen; 10 11 while (scanf("%s%s%s", n, m, p) != EOF) 12 { 13 memset(ni, 0, sizeof(ni)); 14 memset(mi, 0, sizeof(mi)); 15 memset(pi, 0, sizeof(pi)); 16 maxlen = 0; 17 lenn = strlen(n); 18 for (i = lenn - 1; i >= 0; i --) 19 ni[(lenn - 1) - i] = n[i] - '0'; 20 lenm = strlen(m); 21 for (i = lenm - 1; i >= 0; i --) 22 mi[(lenm - 1) - i] = m[i] - '0'; 23 if (lenm == 1 && mi[0] < 3) 24 { 25 printf("NO\n"); 26 continue; 27 } 28 lenp = strlen(p); 29 for (i = lenp - 1; i >= 0; i --) 30 pi[(lenp - 1) - i] = p[i] - '0'; 31 if (lenn > maxlen) 32 maxlen = lenn; 33 if (lenp > maxlen) 34 maxlen = lenp; 35 for (i = 0; i < maxlen; i ++) 36 { 37 ni[i] += pi[i]; 38 ni[i + 1] += ni[i] / 10; 39 ni[i] %= 10; 40 } 41 if (ni[i]) 42 maxlen ++; 43 if (lenm > maxlen) 44 printf("NO\n"); 45 else if (lenm < maxlen) 46 { 47 if (lenp == 1 && pi[0] == 0) 48 printf("NO\n"); 49 else 50 printf("YES\n"); 51 } 52 else 53 { 54 for (i = maxlen - 1; i >= 0; i --) 55 if (ni[i] > mi[i]) 56 { 57 if (lenp == 1 && pi[0] == 0) 58 printf("NO\n"); 59 else 60 printf("YES\n"); 61 break; 62 } 63 else if (ni[i] < mi[i]) 64 { 65 printf("NO\n"); 66 break; 67 } 68 if (i < 0) 69 printf("YES\n"); 70 } 71 } 72 return 0; 73 }
5 题目五 郑厂长系列故事——逃离迷宫
这道题目直接用模拟,从左到右依次消掉箱子,如果不能消完,就失败了,否则就成功。
1 #include <stdio.h> 2 3 long data[1000001]; 4 int main(void) 5 { 6 int t; 7 int n; 8 int i,j; 9 10 scanf("%d", &t); 11 for (i = 1; i <= t; i ++) 12 { 13 scanf("%d", &n); 14 for (j = 1; j <= n; j ++) 15 scanf("%ld", &data[j]); 16 for (j = 1; j <= n - 1; j ++) 17 { 18 if (data[j] > data[j + 1]) 19 break; 20 data[j + 1] -= data[j]; 21 data[j] = 0; 22 } 23 if (j <= n - 1 || data[n] != 0) 24 printf("I will never go out T_T\n"); 25 else 26 printf("yeah~ I escaped ^_^\n"); 27 } 28 return 0; 29 }