总结:
前几次的认证考试都是最后一题困难其他的没啥难度。
值得一提的是第三题画图的坐标转换和一些细节要注意。第四题的送货对欧拉回路的理解要深刻一点,用了并查集处理。第五题依旧不会,bitsit完全没概念。。
题解:
数位之和
问题描述
给定一个十进制整数n,输出n的各位数字之和。
输入格式
输入一个整数n。
输出格式
输出一个整数,表示答案。
样例输入
20151220
样例输出
13
样例说明
20151220的各位数字之和为2+0+1+5+1+2+2+0=13。
评测用例规模与约定
所有评测用例满足:0 ≤ n ≤ 1000000000。
代码:
#include<bits/stdc++.h> using namespace std; int n; void solve() { cin>>n; int ans=0; while(n){ int m=n%10; n/=10; ans+=m; } cout<<ans; } int main() { ios::sync_with_stdio(0); cin.tie(0),cout.tie(0); int t=1; while(t--){ solve(); }return 0; }
消除类游戏
问题描述
消除类游戏是深受大众欢迎的一种游戏,游戏在一个包含有n行m列的游戏棋盘上进行,棋盘的每一行每一列的方格上放着一个有颜色的棋子,当一行或一列上有连续三个或更多的相同颜色的棋子时,这些棋子都被消除。当有多处可以被消除时,这些地方的棋子将同时被消除。
现在给你一个n行m列的棋盘,棋盘中的每一个方格上有一个棋子,请给出经过一次消除后的棋盘。
请注意:一个棋子可能在某一行和某一列同时被消除。输入格式
输入的第一行包含两个整数n, m,用空格分隔,分别表示棋盘的行数和列数。
接下来n行,每行m个整数,用空格分隔,分别表示每一个方格中的棋子的颜色。颜色使用1至9编号。输出格式
输出n行,每行m个整数,相邻的整数之间使用一个空格分隔,表示经过一次消除后的棋盘。如果一个方格中的棋子被消除,则对应的方格输出0,否则输出棋子的颜色编号。
样例输入
4 5
2 2 3 1 2
3 4 5 1 4
2 3 2 1 3
2 2 2 4 4样例输出
2 2 3 0 2
3 4 5 0 4
2 3 2 0 3
0 0 0 4 4样例说明
棋盘中第4列的1和第4行的2可以被消除,其他的方格中的棋子均保留。
样例输入
4 5
2 2 3 1 2
3 1 1 1 1
2 3 2 1 3
2 2 3 3 3样例输出
2 2 3 0 2
3 0 0 0 0
2 3 2 0 3
2 2 0 0 0样例说明
棋盘中所有的1以及最后一行的3可以被同时消除,其他的方格中的棋子均保留。
评测用例规模与约定
所有的评测用例满足:1 ≤ n, m ≤ 30。
代码:
#include<bits/stdc++.h> using namespace std; const int N=35; int g[N][N]; bool st[N][N]; int n,m; void solve() { cin>>n>>m; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ cin>>g[i][j]; } } for(int i=1;i<=n;i++){ int o=g[i][1]; int cnt=1; queue<int>q; q.push(1); for(int j=2;j<=m;j++){ if(g[i][j]==o){ cnt++; q.push(j); }else{ o=g[i][j]; cnt=1; while(q.size()){ q.pop(); } q.push(j); } if(cnt>=3){ while(q.size()){ int t=q.front(); q.pop(); st[i][t]=true; } } } } for(int j=1;j<=m;j++){ int o=g[1][j]; int cnt=1; queue<int> q; q.push(1); for(int i=2;i<=n;i++){ if(g[i][j]==o){ cnt++; q.push(i); }else{ o=g[i][j]; cnt=1; while(q.size()){ q.pop(); } q.push(i); } if(cnt>=3){ while(q.size()){ int t=q.front(); q.pop(); st[t][j]=true; } } } } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(st[i][j]){ cout<<"0 "; }else{ cout<<g[i][j]<<" "; } } cout<<endl; } } int main() { ios::sync_with_stdio(0); cin.tie(0),cout.tie(0); int t=1; while(t--){ solve(); }return 0; }
画图
问题描述
用 ASCII 字符来画图是一件有趣的事情,并形成了一门被称为 ASCII Art 的艺术。例如,下图是用 ASCII 字符画出来的 CSPRO 字样。
..____.____..____..____...___..
./.___/.___||.._.\|.._.\./._.\.
|.|...\___.\|.|_).|.|_).|.|.|.|
|.|___.___).|..__/|.._.<|.|_|.|
.\____|____/|_|...|_|.\_\\___/.
本题要求编程实现一个用 ASCII 字符来画图的程序,支持以下两种操作:
画线:给出两个端点的坐标,画一条连接这两个端点的线段。简便起见题目保证要画的每条线段都是水平或者竖直的。水平线段用字符 - 来画,竖直线段用字符 | 来画。如果一条水平线段和一条竖直线段在某个位置相交,则相交位置用字符 + 代替。
填充:给出填充的起始位置坐标和需要填充的字符,从起始位置开始,用该字符填充相邻位置,直到遇到画布边缘或已经画好的线段。注意这里的相邻位置只需要考虑上下左右 4 个方向,如下图所示,字符 @ 只和 4 个字符 * 相邻。
.*.
*@*
.*.输入格式
第1行有三个整数m, n和q。m和n分别表示画布的宽度和高度,以字符为单位。q表示画图操作的个数。
第2行至第q + 1行,每行是以下两种形式之一:
0 x1 y1 x2 y2:表示画线段的操作,(x1, y1)和(x2, y2)分别是线段的两端,满足要么x1 = x2 且y1 ≠ y2,要么 y1 = y2 且 x1 ≠ x2。
1 x y c:表示填充操作,(x, y)是起始位置,保证不会落在任何已有的线段上;c 为填充字符,是大小写字母。
画布的左下角是坐标为 (0, 0) 的位置,向右为x坐标增大的方向,向上为y坐标增大的方向。这q个操作按照数据给出的顺序依次执行。画布最初时所有位置都是字符 .(小数点)。输出格式
输出有n行,每行m个字符,表示依次执行这q个操作后得到的画图结果。
样例输入
4 2 3
1 0 0 B
0 1 0 2 0
1 0 0 A样例输出
AAAA
A--A样例输入
16 13 9
0 3 1 12 1
0 12 1 12 3
0 12 3 6 3
0 6 3 6 9
0 6 9 12 9
0 12 9 12 11
0 12 11 3 11
0 3 11 3 1
1 4 2 C样例输出
................
...+--------+...
...|CCCCCCCC|...
...|CC+-----+...
...|CC|.........
...|CC|.........
...|CC|.........
...|CC|.........
...|CC|.........
...|CC+-----+...
...|CCCCCCCC|...
...+--------+...
................评测用例规模与约定
所有的评测用例满足:2 ≤ m, n ≤ 100,0 ≤ q ≤ 100,0 ≤ x < m(x表示输入数据中所有位置的x坐标),0 ≤ y < n(y表示输入数据中所有位置的y坐标)。
代码:
#include<bits/stdc++.h> using namespace std; const int N = 100; typedef pair<int, int>PII; int n, m, q; bool st[N][N], sst[N][N]; int id[N][N]; bool st1[N][N]; int dx[] = { 1,-1,0,0 }; int dy[] = { 0,0,1,-1 }; void bfs(int a, int b, int c) { memset(st1, false, sizeof(st1)); queue<PII>q; q.push({ a,b }); st1[a][b] = true; while (q.size()) { auto t = q.front(); q.pop(); int x = t.first; int y = t.second; for (int i = 0;i < 4;i++) { int sx = x + dx[i]; int sy = y + dy[i]; if (st[sx][sy] || sst[sx][sy]) { continue; }if (st1[sx][sy]) { continue; }if (sx<0 || sx>m || sy<0 || sy>n) { continue; } q.push({ sx,sy }); st1[sx][sy] = true; } } for (int i = 0;i < m;i++) { for (int j = 0;j < n;j++) { if (st1[i][j]) { id[i][j] = c; } } } } void solve() { cin >> m >> n >> q; for (int i = 1;i <= q;i++) { int k; cin >> k; if (k == 0) { int x1, x2, y1, y2; cin >> x1 >> y1 >> x2 >> y2; if (x1 == x2) { if (y1 < y2) { for (int j = y1;j <= y2;j++) { st[x1][j] = true; } } else { for (int j = y2;j <= y1;j++) { st[x1][j] = true; } } } else if (y1 == y2) { if (x1 < x2) { for (int j = x1;j <= x2;j++) { sst[j][y1] = true; } } else { for (int j = x2;j <= x1;j++) { sst[j][y1] = true; } } } } else { int x, y; char c; cin >> x >> y >> c; if (st[x][y] || sst[x][y]) { continue; } int z = c; bfs(x, y, z); } } for (int j = n - 1;~j;j--) { for (int i = 0;i < m;i++) { if (st[i][j] && sst[i][j]) { cout << "+"; } else if (st[i][j] && !sst[i][j]) { cout << "|"; } else if (sst[i][j] && !st[i][j]) { cout << "-"; } else { if (!id[i][j]) { cout << "."; } else { char c = id[i][j]; cout << c; } } } cout << endl; } } int main() { ios::sync_with_stdio(0); cin.tie(0), cout.tie(0); int t = 1; while (t--) { solve(); }return 0; }
送货
问题描述
为了增加公司收入,F公司新开设了物流业务。由于F公司在业界的良好口碑,物流业务一开通即受到了消费者的欢迎,物流业务马上遍及了城市的每条街道。然而,F公司现在只安排了小明一个人负责所有街道的服务。
任务虽然繁重,但是小明有足够的信心,他拿到了城市的地图,准备研究最好的方案。城市中有n个交叉路口,m条街道连接在这些交叉路口之间,每条街道的首尾都正好连接着一个交叉路口。除开街道的首尾端点,街道不会在其他位置与其他街道相交。每个交叉路口都至少连接着一条街道,有的交叉路口可能只连接着一条或两条街道。
小明希望设计一个方案,从编号为1的交叉路口出发,每次必须沿街道去往街道另一端的路口,再从新的路口出发去往下一个路口,直到所有的街道都经过了正好一次。输入格式
输入的第一行包含两个整数n, m,表示交叉路口的数量和街道的数量,交叉路口从1到n标号。
接下来m行,每行两个整数a, b,表示和标号为a的交叉路口和标号为b的交叉路口之间有一条街道,街道是双向的,小明可以从任意一端走向另一端。两个路口之间最多有一条街道。输出格式
如果小明可以经过每条街道正好一次,则输出一行包含m+1个整数p1, p2, p3, ..., pm+1,表示小明经过的路口的顺序,相邻两个整数之间用一个空格分隔。如果有多种方案满足条件,则输出字典序最小的一种方案,即首先保证p1最小,p1最小的前提下再保证p2最小,依此类推。
如果不存在方案使得小明经过每条街道正好一次,则输出一个整数-1。样例输入
4 5
1 2
1 3
1 4
2 4
3 4样例输出
1 2 4 1 3 4
样例说明
城市的地图和小明的路径如下图所示。
样例输入
4 6
1 2
1 3
1 4
2 4
3 4
2 3样例输出
-1
样例说明
城市的地图如下图所示,不存在满足条件的路径。
评测用例规模与约定
前30%的评测用例满足:1 ≤ n ≤ 10, n-1 ≤ m ≤ 20。
前50%的评测用例满足:1 ≤ n ≤ 100, n-1 ≤ m ≤ 10000。
所有评测用例满足:1 ≤ n ≤ 10000,n-1 ≤ m ≤ 100000。代码:
#include <bits/stdc++.h> using namespace std; const int N = 10010; int n,m; set<int> g[N]; int p[N]; int ans[100010],top; int find(int x) // 并查集 { if (p[x] != x) p[x] = find(p[x]); return p[x]; } void dfs(int u){ while(g[u].size()){ int t=*g[u].begin(); g[u].erase(t),g[t].erase(u); dfs(t); } ans[++top]=u; } int main() { scanf("%d%d", &n, &m); for(int i=1;i<=n;i++) p[i]=i; while(m--){ int a,b; scanf("%d%d",&a,&b); g[a].insert(b),g[b].insert(a); p[find(a)]=find(b); } int s=0; for(int i=1;i<=n;i++){ if(find(i)!=find(1)){ puts("-1"); return 0; } else if(g[i].size()%2) s++; } if(s!=0&&s!=2||s==2&&g[1].size()%2==0){ puts("-1"); return 0; } dfs(1); for(int i=top;i;i--) printf("%d ",ans[i]); return 0; }