Final Results
-- case number --
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
dance2 * * * * * * * * * *
hexagon * x * x x * x * * x x x x x x x
treats * * * * * * * * * *
时间分配:
读题花了大概半小时,第一题是括号匹配问题,第二题是模拟题,第三题是BFS。大概的思路有了,接下来开始编写程序了。
这三道题中最难的应是第三题,于是决定先做第三题。
第三题:hexagon
难点1:怎么去保存这张表
只能用数组保存了,就把图中的格点都下沉,像个小房子的数组;
难点2:怎样实现数字与图中对应
用了预处理实现数组坐标和数字之间的映射
难点3:怎样找相连的边
这个地方要考虑仔细一点,因为边界情况有点复杂。
最多也就六个相连的点,暴力一下,分别算出来;
难点4:怎样处理左右相邻不同的情况
具体联系题目中的图,要分三种情况去想,做的时候本想偷懒,把中间的合并到两边去了,但是不对的,在补赛完后才发现了。
第二题:treats
难点1:读题
题目的文字叙述比较多,所以要仔细不要漏掉细节;
难点2:怎样去实现
如果每次找一个不被挑过的最大的,则时间代价太大,达到O(n^5);
可以另外给排序,从大到小依次取,但就涉及到保存表的问题,要能把信息还原回去,我是用空间换时间,开了1,000,000的两个数组,映射回去值对应的坐标;由于表是在进行着动态交换的,所以两个大数组也要动态更新,还好更新不难;最后是怎么交换的问题,由于行优先,所以要先去找可以往前移的行去交换,然后在去找可以往前移的列交换;基于每次肯定要靠前移,被占用的行和列肯定是连续的,所以保存一个指针,指向当前可以交换的最小行列,就可以判断交换是否可以进行,但是这个指针也是要动态更新的,有些点可以本身不需要交换,但是他们也会占有相应的行列;
第一题:dance2
难点1:效率
如果真的老老实实去一对一对括号拆的话,编程复杂度较高,可能用指针实现会好些;但时间效率是比较低的;
由于题目没有要求给出组合的方式,所以可以利用括号的一些性质,由于括号的形式是<>(题目中是><),所以在任何地方<的个数不会比>的个数少,否则只能往><的方向发展了;最后两个方向个数要一致,就一定有一种方案可以配对了(证明??)
至于证明,可以用数学归纳法吧:
(1)当有n = 1对时,肯定是<>,存在配对方案;
(2)假设当n = k对时,存在配对方案;
当n = k+1是,易知第一个和最后一个一定是<,从左向右在位置i找到第一个>,则1 —— i-1都是<,把i-1和i配对,则剩下的一串仍此前所给符合要求,且有k对,由(2) 知,存在配对方案;
(4)综上符合上述条件的必存在一种配对方案。
心得:
1.造数据寻找BUG是十分重要的;
2.在一段程序前加COMMENT会使程序思路会清晰很多;
3.慢慢适应用中间结果方式分块检查程序的正确性;
4.大数组放在主函数外,其余尽量放在主函数内,循环变量在循环体内声明;
5.自信点,不要以为什么都不会证明,第一题的证明还是在能力范围内的,要去尝试;
6.数据范围还欠仔细,应该卡着估计,不应该放着估计,最后再适当加点;有的时候是数量级的估计错误;
7.if <> else <>嵌套小心忘记 else
My Code
hexagon.cpp
/* ID: zhangji42 PROG: hexagon LANG: C++ */ #include <stdio.h> #include <string.h> const int maxK = 50+3, maxP = 50*49*3+1+10;//最终还是数据的范围估计错了,d[maxK] should be d[maxK*2-1] int d[maxK*2-1][maxK*2-1], map[maxP][7], q[maxP], dis[maxP], ans[maxP]; bool vis[maxP]; int main(){ freopen("hexagon.in", "r", stdin); freopen("hexagon.out", "w", stdout); int K, H, L; scanf("%d%d%d", &K, &H, &L); /*build the f:2d to number*/ int len = K, counter = 0;; for (int i = 1; i <= 2*K-1; i++) { for (int j = 1; j <= len; j++) { d[i][j] = ++counter; //printf("%d %d:%d/n", i, j, counter); } if (i < K) len++; else len--; } /*build every point's neighbours*/ len = K; memset(map,0,sizeof(map)); for (int i = 1; i <= 2*K-1; i++) { for (int j = 1; j<= len; j++) { if (j < len) map[d[i][j]][1] = d[i][j+1];//up if (j > 1) map[d[i][j]][2] = d[i][j-1];//down if (i < K) { if (j < len) map[d[i][j]][3] = d[i-1][j]; map[d[i][j]][4] = d[i-1][j-1]; map[d[i][j]][5] = d[i+1][j]; map[d[i][j]][6] = d[i+1][j+1]; } else if (i > K) {// 漏掉了一个else,好久才检查出来 map[d[i][j]][3] = d[i-1][j]; map[d[i][j]][4] = d[i-1][j+1]; if (j < len) map[d[i][j]][5] = d[i+1][j]; map[d[i][j]][6] = d[i+1][j-1]; } else { if (j < len) map[d[i][j]][3] = d[i-1][j]; map[d[i][j]][4] = d[i-1][j-1]; if (j < len) map[d[i][j]][5] = d[i+1][j]; map[d[i][j]][6] = d[i+1][j-1]; } /*for (int k = 1; k <= 6; k++) printf("%d-%d %d/n", d[i][j], k, map[d[i][j]][k]);*/ } if (i < K) len++; else len--; } /*BFS is a smart solution*/ int full = 1, now = 1, anslen = 0; dis[1] = 0; q[1] = H; memset(vis,0,sizeof(vis)); memset(ans,0,sizeof(ans)); vis[H] = 1; vis[0] = 1; while (now <= full) { //printf("%d/n", q[now]); if (dis[now] < L) { for (int i = 1; i <= 6; i++) if (!vis[map[q[now]][i]]) { full++; q[full] = map[q[now]][i]; vis[q[full]] = 1; dis[full] = dis[now]+1; } } else ans[++anslen] = q[now]; now++; } /*sort the point*/ for (int i = 1; i < anslen; i++) for (int j = i+1; j <= anslen; j++) if (ans[i] > ans[j]) { int temp = ans[i]; ans[i] = ans[j]; ans[j] = temp; } /*print*/ printf("%d/n", anslen); for (int i = 1; i <= anslen; i++) printf("%d/n", ans[i]); return 0; }
treats.cpp
/* ID: zhangji42 PROG: treats LANG: C++ */ #include <stdio.h> const int max = 25+5, maxf = 1000010; int map[max][max], m, n, x[maxf], y[maxf], d[max*max]; void swap_line(int lx, int ly) { for (int j = 1; j <= m; j++) { int temp = map[lx][j]; map[lx][j] = map[ly][j]; map[ly][j] = temp; x[map[lx][j]] = lx; x[map[ly][j]] = ly; } } void swap_column(int cx, int cy) { for (int i = 1; i <= n; i++) { int temp = map[i][cx]; map[i][cx] = map[i][cy]; map[i][cy] = temp; y[map[i][cx]] = cx; y[map[i][cy]] = cy; } } int main(){ freopen("treats.in", "r", stdin); freopen("treats.out", "w", stdout); /*read the data*/ scanf("%d %d", &m, &n); int t = 0; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { scanf("%d", &map[i][j]); x[map[i][j]] = i; y[map[i][j]] = j; d[++t] = map[i][j]; } /*sort the data*/ for (int i = 1; i < t; i++) for (int j = i+1; j <= t; j++) if (d[i] < d[j]) { int temp = d[i]; d[i] = d[j]; d[j] = temp; } /*deal with treat from max to min*/ int pline = 1, pcolumn = 1; for (int i = 1; i <= t; i++) { //printf("%d/n", d[i]); int nowx = x[d[i]], nowy = y[d[i]]; if (nowx > pline) swap_line(nowx, pline); if (nowy > pcolumn) swap_column(nowy, pcolumn); if (x[d[i]]+1 > pline) pline = x[d[i]]+1; if (y[d[i]]+1 > pcolumn) pcolumn = y[d[i]]+1; } /*print*/ for (int i = 1; i <= n; i++) { printf("%d", map[i][1]); for (int j = 2; j <= m; j++) printf(" %d", map[i][j]); printf("/n"); } return 0; }
dance2.cpp
/* ID: zhangji42 PROG: dance2 LANG: C++ */ #include <stdio.h> char c[210]; int main(){ freopen("dance2.in", "r", stdin); freopen("dance2.out", "w", stdout); int cases; scanf("%d", &cases); while (cases-- > 0) { int len; scanf("%d %s", &len, c); //printf("%s/n", c); int a = 0, b = 0; bool flag = true; if (len & 1 == 1) flag = false; else for (int i = 0; i < len; i++) if (c[i] == '>') a++; else { b++; if (b > a) { flag = false; break; } } if (a != b) flag = false; if (flag) printf("legal/n"); else printf("illegal/n"); } return 0; }