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
", 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
", 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
");
108         else
109             printf("%d
", 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
");
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
");
45         else if (lenm < maxlen)
46         {
47             if (lenp == 1 && pi[0] == 0)
48                 printf("NO
");
49             else
50                 printf("YES
");
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
");
59                     else
60                         printf("YES
");
61                     break;
62                 }
63                 else if (ni[i] < mi[i])
64                 {
65                     printf("NO
");
66                     break;
67                 }
68             if (i < 0)
69                 printf("YES
");
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
");
25         else
26             printf("yeah~ I escaped ^_^
");
27     }
28     return 0;
29 }