第二届校内程序设计选拔赛部分题解
2014-10-15 16:31
309 查看
前言
这次比赛共5道题(中文),个人赛。我负责命题3道,这里就写这3题的解题报告。总的来说题目难度不大,考虑到毕竟比赛只有2个小时。代号1是字符串水题;代号3是一道经典、简单的动态规划,但我改编后加大了难度;代号2是裸广度优先搜索,但是要搜两轮,考验编程熟练度。我觉得后两道难度中等吧,还算不上难题。
我考的这些知识点:bfs、读入外挂、滚动数组等,都是比较基本的概念,网上一搜资料一堆,所以我的解题报告会偏精简。然后标程用的都是C++,不懂C++的同学还是抓紧学习吧,玩ACM不会C++很吃亏。
代号1
判断一个0~1内的高精度小数是否严格大于0.99999999999999999999(20个9)。- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
坑点1:注意double精度只有16位有效数字,故必须用字符串处理。
坑点2:除了小数点后判断是否出现连续的20个9,还要注意判断接下来是否有非0值。即0.99999999999999999999对应输出的是“No”,估计这一点比赛的时候会让很多人WA,甚至WA了还很难想明白为什么。
#include <iostream> #include <string> using namespace std; string s; bool func() { int i; if (s.size() < 23) return 0; for (i = 2; i <= 21; i++) if (s[i] != '9') return 0; while (i < s.size()) if (s[i++] != '0') return 1; return 0; } int main() { int T; cin >> T; while (cin >> s) cout << (func()?"Yes":"No") << "\n"; return 0; }
代号2
一个10*10的网格,一个起点A,六个目的地1~6中任选两个,问最短距离是多少。- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
这题其实算法并不难,主要是考验编程熟练度,能否在有限的比赛时间内完成代码,题型为BFS。
坑点:注意虽然解一定存在,不代表每个食堂一定能到达,可能一个食堂上下左右会被封锁,估计这点会造成一些人RE。不过更有可能的是因为时间原因,比较少人会选择做这题。后来我把样例改成现在这样,把这个坑点直接告诉大家了。所以降低了难度,能过样例的基本能AC。
注意标程的一些编程技巧,特别是6个食堂选2个的地方,可以直接用双循环暴力。
#include <algorithm> #include <cstdio> #include <cstring> #include <iostream> #include <queue> using namespace std; const int inf = 99999999; bool can[12][12]; // can[i][j]:原始地图(i,j)点是否可以走 // 在地图中,从(x0,y0)到(x1,y1)的距离 int distance(int x0, int y0, int x1, int y1) { int dis[12][12] = {}, x, y, d; // dis用0值代表还未访问 dis[x0][y0] = 1; // 距离都多加1,最后返回时注意减1 queue<int> pos; pos.push(100 * x0 + y0); while(pos.size()) { x = pos.front()/100; // 横坐标 y = pos.front()%100; // 纵坐标 d = dis[x][y]; pos.pop(); // 出队 if (x == x1 && y == y1) return d-1; #define TEST if(can[x][y] && !dis[x][y]) {dis[x][y]=d+1; pos.push(100*x+y);} x += 1, y = y; TEST // 上 x -= 2, y = y; TEST // 下 x += 1, y -= 1; TEST // 左 y += 2; TEST // 右 } return inf; // 无解 } int main() { string s; int T, x[7], y[7], i, j, ans; // 存储起点及食堂的坐标 scanf("%d ", &T); while (T--) { memset(can, 0, sizeof(can)); for (i = 0; i< 10; i++) { getline(cin, s); for (j = 0; j < 10; j++) { // 地图编号从1开始 if (s[j] != '#') can[i+1][j+1] = 1; if (s[j] > '0' && s[j] < '7') x[s[j]-'0'] = i+1, y[s[j]-'0'] = j+1; else if (s[j] == 'A') x[0] = i+1, y[0] = j+1; } } ans = inf; for (i = 1; i <= 6; i++) for (j = 1; j <= 6; j++) { if (j == i) continue; ans = min(ans, distance(x[0],y[0],x[i],y[i])+distance(x[i],y[i],x[j],y[j])); } cout << ans << "\n"; if (T) getchar(); // 读掉空行 } return 0; }
代号3
一道很经典的动态规划三角形,问从上往下走和最大的走法。但是一般的数据规模是1千行,这里被我放大到3千行。- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
从1千行到3千行,数量是个平方级增长的过程。本来我故意把整数范围设成long long大小,是想让开二维数组解的人直接MLE,不过3000*3000只要44M内存还好~。然后要读入的整数数量非常大,要用读入外挂优化,考虑到降低难度,所以在题目正文直接提到了要用读入外挂做,暗示用scanf会TLE。大白书第40页也有读入外挂的模板,我这里C++版的读入外挂是个函数模板,可以读取任意整型的整数。
那么不用二维数据怎么解呢?用滚动数组,开个a[2][3001]就够了。可以边导入数据边运算,在每一行,都更新为从第一行到该点的最优解值。最后判断最后一行中的最大值即可。
不太明白动态规划原理的同学,可以看小白书或紫书动态规划那一章,开篇就是讲数字三角形。
#include <algorithm> #include <cstdio> #include <iostream> using namespace std; typedef unsigned long long LL; //仅读正整数的读入外挂 template <typename T> inline void read(T& x) { char ch; while (!((((ch=getchar())>='0') && (ch <= '9')) || (ch == '-'))); x = ch-'0'; while (((ch=getchar())>='0') && (ch <= '9')) x = x*10+ch-'0'; } int main() { int n, i, j, now, T; read(T); while (T--) { read(n); LL a[2][3001] = {}; for (now = i = 1; i <= n; i++) { now ^= 1; for (j = 1; j <= i; j++) { read(a[now][j]); a[now][j] += max(a[now^1][j-1], a[now^1][j]); } } cout << *max_element(&a[now][1], &a[now][n+1]) << "\n"; } return 0; }
后记
看来还是出难了,结果有点惨烈~~~C题本来卡32M内存的,但是校OJ给的是64M,所以也可以用开辟二维数组做,但要注意代码效率。文中小白书指的是刘汝佳的《算法竞赛入门经典》,大白书是《算法竞赛入门经典——训练指南》,紫书是指小白书的第二版,是非常好的ACM学习教材,推荐大家使用。
解题报告有疑问的可以跟我交流。
相关文章推荐
- 南邮2014程序设计新生赛暨蓝桥杯校内自主选拔赛2
- 南邮2014程序设计新生赛暨蓝桥杯校内自主选拔赛
- 第五届“蓝桥杯”全国软件 校内选拔赛试题(Java组)11、(18分) 身份证的奥秘
- 2017年第0届浙江工业大学之江学院程序设计竞赛决赛部分题解
- 12_10_8校内PK 部分补题 # nobody
- Windows CE 程序设计 (3rd 版)--5.2 公共控件(部分)
- 校第十六届大学生程序设计竞赛暨2016省赛集训队选拔赛1007
- HDU2010省赛集训队选拔赛(校内赛) H
- 设计模式李建忠(面向对象程序设计部分)
- 第二届北京林业大学“计蒜客”杯程序设计竞赛 G题 易彰彪的一张表
- SDUT 2165 Crack Mathmen(快速幂)山东省第二届ACM大学生程序设计竞赛
- 第二部分 Windows编程、面向对象程序设计
- 第二届北师大程序设计竞赛
- 团体程序设计天梯赛-习题集部分题解(大牛勿喷)
- ctf.360.cn第二届,逆向部分writeup――第一题
- 第六届蓝桥杯校内选拔赛C/C++高职组解题(5)
- ctf.360.cn第二届,逆向部分writeup――第五题
- 记第一次校内选拔赛
- [2011山东省第二届ACM大学生程序设计竞赛]——Mathmen
- 2014年第四届“华为杯”南邮大学生程序设计竞赛之选拔赛 D演唱顺序问题