XUPT 寒假算法集训第三周
A - 迷宫(一)
一天SLT掉进了一个迷宫里面,SLT想逃出去,可怜的SLT连迷宫是否有能逃出去的路都不知道。
看在SLT这么可怜的份上,就请聪明的你告诉SLT是否有可以逃出去的路。
输入格式
第一行输入两个整数 n 和 m,表示这是一个n×m 的迷宫。
接下来的输入一个 n 行 m 列的迷宫。其中
'S'
表示SLT的位置,'*'
表示墙,SLT无法通过,'.'
表示路,SLT可以通过'.'
移动,'T'
表示迷宫的出口(SLT每次只能移动到四个与他相邻的位置——上,下,左,右)。输出格式
输出一个字符串,如果SLT可以逃出迷宫输出
"yes"
,否则输出"no"
。数据范围
1≤n,m≤10。
Sample 1
Inputcopy Outputcopy 3 4 S**. ..*. ***T noSample 2
Inputcopy Outputcopy 3 4 S**. .... ***T yes
广搜
#include<stdio.h>
#include<iostream>
using namespace std;
int n, m, dir[4][2] = { {0,1},{1,0},{0,-1},{-1,0} },book[12][12];
char a[12][12];
struct node
{int x, y;
}queue[110];
int main()
{int startx, starty, p = 0, q = 0, tx, ty, head, tail, flag = 0;cin >> n >> m;for (int i = 0; i < n; i++)for (int j = 0; j < m; j++){cin >> a[i][j];if (a[i][j] == 'S'){startx = i;starty = j;}if (a[i][j] == 'T'){p = i;q = j;}}head = 0;tail = 0;queue[tail].x = startx;queue[tail].y = starty;tail++;book[startx][starty] = 1;while (head < tail){for (int i = 0; i < 4; i++){tx = queue[head].x + dir[i][0];ty = queue[head].y + dir[i][1];if (tx<0 || tx>=n || ty<0 || ty>=m) continue;if (a[tx][ty] != '*' && book[tx][ty] == 0){book[tx][ty] = 1;queue[tail].x = tx;queue[tail].y = ty;tail++;}if (tx==p && ty==q){flag = 1;break;}}if (flag == 1){break;}head++;}if(flag==1) printf("yes");else if (flag == 0) printf("no");return 0;
}
B - 迷宫(二)
SLT在你的帮助下终于逃出了迷宫,但是SLT并没有沉浸于喜悦之中,而是很快的又陷入了思考,从这个迷宫逃出的最少步数是多少呢?
输入格式
第一行输入两个整数 n 和 m,表示这是一个 n×m 的迷宫。
接下来的输入一个 n 行 m 列的迷宫。其中
'S'
表示SLT的位置,'*'
表示墙,SLT无法通过,'.'
表示路,SLT可以通过'.'
移动,'T'
表示迷宫的出口(SLT每次只能移动到四个与他相邻的位置——上,下,左,右)。输出格式
输出整数,表示SLT逃出迷宫的最少步数,如果SLT无法逃出迷宫输出 −1。
数据范围
1≤n,m≤10。
Sample 1
Inputcopy Outputcopy 3 4 S**. ..*. ***T -1Sample 2
Inputcopy Outputcopy 3 4 S**. .... ***T 5
与A题不一样的就是如果可以走出去, 就输出步数, 否则输出-1
所以在结构体多一个步数变量就好
#include<stdio.h>
#include<iostream>
using namespace std;
int flag, book[12][12], n, m;
char a[12][12];
struct note
{int x, y, s; //s表示步数
}que[110];
int main()
{int next[4][2] = { {0,1},{1,0},{0,-1},{-1,0} };int tx, ty, p, q, startx, starty, head = 0, tail = 0;int min = 99999999;cin >> n >> m;for (int i = 0; i < n; i++)for (int j = 0; j < m; j++){cin >> a[i][j];if (a[i][j] == 'S'){startx = i;starty = j;}if (a[i][j] == 'T'){p = i;q = j;}}book[startx][starty] = 1;que[tail].x = startx;que[tail].y = starty;que[tail].s = 0;tail++;while (head < tail){for (int i = 0; i < 4; i++){tx = que[head].x + next[i][0];ty = que[head].y + next[i][1];if (tx < 0 || ty < 0 || tx >= n || ty >= m) continue;if (a[tx][ty] != '*' && book[tx][ty] == 0){book[tx][ty] = 1;que[tail].x = tx;que[tail].y = ty;que[tail].s = que[head].s + 1;tail++;}if (tx == p && ty == q){if (que[tail-1].s < min) min = que[tail-1].s;flag = 1;break;}}if (flag == 1) break;head++;}if (flag == 1) printf("%d",min);else printf("-1");return 0;
}
C - 迷宫(三)
注意读清楚题! ! ! 真的是服了自己, 每个最外围的 '.' 都是出口, 还有开始位置不算步数
还有就是注意范围, 因为直接复制上面的代码, 范围小了, 出错了...
Status | Segmentation Fault |
---|
经过思考SLT终于解决了怎么计算一个迷宫的最短路问题,于是SLT找到一个新的迷宫图,来验证自己是否真的会计算一个迷宫的最短路。
为了检验自己计算的是否正确,SLT特邀你一起来计算。
输入格式
第一行输入两个整数 n 和 m,表示这是一个 n×m 的迷宫。
接下来的输入一个 n 行 m 列的迷宫。其中
'@'
表示SLT的位置,'#'
表示墙,SLT无法通过,'.'
表示路,SLT可以通过'.'
移动,所有在迷宫最外围的'.'
都表示迷宫的出口(SLT每次只能移动到四个与他相邻的位置——上,下,左,右)。输出格式
输出整数,表示SLT逃出迷宫的最少步数,如果SLT无法逃出迷宫输出 −1。
数据范围
1≤n,m≤15。
Sample 1
Inputcopy Outputcopy 9 13 ############# #@..........# #####.#.#.#.# #...........# #.#.#.#.#.#.# #.#.......#.# #.#.#.#.#.#.# #...........# #####.####### 11Sample 2
Inputcopy Outputcopy 4 6 #.#### #.#.## #...@# ###### 5
#include<stdio.h>
#include<iostream>
using namespace std;
int flag, book[20][20], n, m;
char a[20][20];
struct note
{int x, y, s;
}que[200];
int main()
{int next[4][2] = { {0,1},{1,0},{0,-1},{-1,0} };int tx, ty, p, q, startx, starty, head = 0, tail = 0;int min = 99999999;cin >> n >> m;for (int i = 0; i < n; i++)for (int j = 0; j < m; j++){cin >> a[i][j];if (a[i][j] == '@'){startx = i;starty = j;}}book[startx][starty] = 1;que[tail].x = startx;que[tail].y = starty;que[tail].s = 0;tail++;while (head < tail){for (int i = 0; i < 4; i++){tx = que[head].x + next[i][0];ty = que[head].y + next[i][1];if (tx < 0 || ty < 0 || tx >= n || ty >= m) continue;if (a[tx][ty] != '#' && book[tx][ty] == 0){book[tx][ty] = 1;que[tail].x = tx;que[tail].y = ty;que[tail].s = que[head].s + 1;tail++;}if (a[tx][ty]=='.'&&(tx==0||tx==n-1||ty==0||ty==m-1)){if (que[tail - 1].s < min) min = que[tail - 1].s;flag = 1;break;}}if (flag == 1) break;head++;}if (flag == 1) printf("%d", min);else printf("-1");return 0;
}
E - 4 Values whose Sum is 0
这个题要注意不能直接搜索, 不能时间是 n^4 ,必然TLE, 所以要利用分治思想, 前两组求和, 后两组求和, 相加看是否为0
给你四个数列A,B,C,D。从每个数列中各取出一个数,问有多少种方案使得4个数的和为0。
当一个数列中有多个相同的数字的时候,把它们当做不同的数对待。Input
第一行:n(代表数列中数字的个数) (1≤n≤4000)
第二行:依次输入A,B,C,D(数字不超过2的28次方)Output
输出不同组合的个数。
Sample Input
6
-45 22 42 -16
-41 -27 56 30
-36 53 -37 77
-36 30 -75 -46
26 -38 -10 62
-32 -54 -6 45Sample Output
5
Hint
样例解释: (-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46),(-32, 30, -75, 77), (-32, -54, 56, 30).
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int n,t,a[4005],b[4005],c[4005],d[4005], s1[16000005],s2[16000005];
int main()
{scanf("%d",&n);for(int i=0;i<n;i++)scanf("%d %d %d %d",&a[i],&b[i],&c[i],&d[i]);int cnt=0;for(int i=0;i<n;i++){for(int j=0;j<n;j++){s1[cnt]=a[i]+b[j];s2[cnt]=c[i]+d[j];cnt++;}} sort(s1,s1+cnt);sort(s2,s2+cnt);int r=cnt-1; //数组的右端点for(int l=0;l<cnt;l++){while(r>=0 && (s1[l]+s2[r])>0) //缩小右边界r--;if(r<0) break;int r1=r; //可能有好几组互相对应while(r1>=0 && (s1[l]+s2[r1])==0){t++;r1--; } }printf("%d",t);return 0;
}
G - Red and Black
再次注意看题! ! ! 给的输入是先列后行...还有字符串读入会涉及换行问题, 如果用scanf读入, 每次都要用getchar()读入换行, 最简单的是用cin读入, 但是cin速度稍慢一点
有一个长方形的房间,覆盖了正方形的磁砖。每块磁砖的颜色,要么是红色,要么是黑色。一名男子站在一块黑色的磁砖上。他可以从一块磁砖移至相邻四块磁砖中的某一块。但是,他不允许在红色磁砖上移动,他只允许在黑色磁砖上移动。
编写一个程序,使得他允许重复上述的移动,判断他所能到达的黑色磁砖的数量。
输入
输入由多个数据集组成。数据集的起始行包含了两个正整数 W 和 H;W 和 H 分别是 x- 和 y- 方向的磁砖数量。W 和 H 不超过 20 。
在数据集中,还有 H 行,每行包含了 W 个字符。每个字符按如下方式表示一块磁砖的颜色。
'.' - 一块黑色的磁砖
'#' - 一块红色的磁砖
'@' - 一名男子,站在一块黑色磁砖上 (在一个数据集中,恰好出现一次)以包含两个 0 的一行,表示输入结束。
输出
对于每个数据集,程序应当输出一行,包含他从初始磁砖所能抵达的磁砖数量 (包括初始磁砖自身)。
示例输入
6 9 ....#. .....# ...... ...... ...... ...... ...... #@...# .#..#. 11 9 .#......... .#.#######. .#.#.....#. .#.#.###.#. .#.#..@#.#. .#.#####.#. .#.......#. .#########. ........... 11 6 ..#..#..#.. ..#..#..#.. ..#..#..### ..#..#..#@. ..#..#..#.. ..#..#..#.. 7 7 ..#.#.. ..#.#.. ###.### ...@... ###.### ..#.#.. ..#.#.. 0 0示例输出
45 59 6 13
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
char a[25][25];
int book[25][25], w, h, cnt, step;
int dfs(int x, int y)
{int next[4][2] = { {1,0},{0,1},{-1,0},{0,-1} }, tx, ty;for (int i = 0; i < 4; i++){tx = x + next[i][0];ty = y + next[i][1];if (tx < 0 || ty < 0 || tx >= h || ty >= w) continue;if (a[tx][ty] == '.' && book[tx][ty] == 0){book[tx][ty] = 1;step++;dfs(tx, ty);}}return step;
}
int main()
{while (1){int p = 0, q = 0;memset(book, 0, sizeof(book));scanf("%d %d", &w, &h);if (w == 0 && h == 0) break;getchar(); //读入换行for (int i = 0; i < h; i++){for (int j = 0; j < w; j++){cin >> a[i][j];if (a[i][j] == '@'){p = i;q = j;}}}step = 1; //起点的步数也算int sum = dfs(p, q);printf("%d\n", sum);}return 0;
}
H - Lake Counting
这个题一开始理解就有点问题, 正确理解是: 从第一个W开始, 遍历八个方向, 遇到 'W' 继续遍历, 最后只剩'.' 结束, 这样算一个水塘 , 这题跟啊哈算法上, 第四章第五节宝岛探险, 涂色问题很像
由于最近的降雨,农夫约翰的农田里形成了不同位置的水塘。农田被表示为一个矩形,它包含了 N x M (1 <= N <= 100; 1 <= M <= 100) 个小方格。每个方格中,要么包含了水 ('W'),要么包含了旱地 ('.')。农夫约翰想要弄清楚,他的农田中形成了多少个水塘。一个水塘是由包含了水的方格连通而成,这里一个方格被视作与周围的全部八个方格相邻。
给出农夫约翰的农田数据图,判断图中有多少个水塘。
输入
* 第一行:两个以空格分隔的整数: N 和 M
* 第 2..N+1 行:每行 M 个字符,表示农夫约翰的农田中的一行。每个字符要么是 'W' 要么是 '.'。字符之间没有空格。
输出
* 第一行:农夫约翰的农田中,水塘的数量。
示例输入
10 12 W........WW. .WWW.....WWW ....WW...WW. .........WW. .........W.. ..W......W.. .W.W.....WW. W.W.W.....W. .W.W......W. ..W.......W.示例输出
3提示
输出细节:
有 3 个水塘:一个位于左上方,一个位于左下方,还有一个位于右边。
#include<stdio.h>
#include<iostream>
using namespace std;
int n, m, p, q, book[100][100], next1[8][2] = { {0,1},{1,0},{0,-1},{-1,0},{-1,-1},{-1,1},{1,-1},{1,1} };
char a[100][100];
void dfs(int x, int y)
{int tx, ty;for (int i = 0; i < 8; i++){tx = x + next1[i][0];ty = y + next1[i][1];if (tx<0 || ty<0 || tx>n || ty>m) continue;if (a[tx][ty] == 'W'){a[tx][ty] = '.';dfs(tx, ty);}}
}
int main()
{int flag=0;cin >> n >> m;for (int i = 0; i < n; i++)for (int j = 0; j < m; j++)cin >> a[i][j];for (int i = 0; i < n; i++)for (int j = 0; j < m; j++){if (a[i][j] == 'W'){flag++;p = i;q = j;dfs(p, q);}}printf("%d", flag);return 0;
}
L - 棋盘问题
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。
Input
输入含有多组测试数据。
每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目。 n <= 8 , k <= n
当为-1 -1时表示输入结束。
随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域, . 表示空白区域(数据保证不出现多余的空白行或者空白列)。Output
对于每一组数据,给出一行输出,输出摆放的方案数目C (数据保证C<2^31)。
Sample
Inputcopy Outputcopy 2 1 #. .# 4 4 ...# ..#. .#.. #... -1 -1 2 1
#include<stdio.h>
#include<iostream>
using namespace std;
int n, k, sum, book[10];
long long t;
char a[10][10];
void dfs(int x)
{if (sum == k){t++;return;}if (x >= n) return;for (int i = 0; i < n; i++){if (book[i] == 0 && a[x][i] == '#'){book[i] = 1;sum++;dfs(x + 1);book[i] = 0;sum--;}}dfs(x + 1);
}
int main()
{int p, q;while (1){scanf("%d %d", &n, &k);if (n == -1 && k == -1) break;for (int i = 0; i < n; i++)for (int j = 0; j < n; j++)cin >> a[i][j];sum = 0;t = 0;dfs(0);printf("%lld\n", t);}return 0;
}
P - 马走日
注意审题啊! ! 要走过所有的点, 所以统计步数是, 最终步数等于棋盘上所有的点, 起始的位置也算一步
马在中国象棋以日字形规则移动。
请编写一段程序,给定n*m大小的棋盘,以及马的初始位置(x,y),要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点。
Input
第一行为整数T(T < 10),表示测试数据组数。
每一组测试数据包含一行,为四个整数,分别为棋盘的大小以及初始位置坐标n,m,x,y。(0<=x<=n-1,0<=y<=m-1, m < 10, n < 10)Output
每组测试数据包含一行,为一个整数,表示马能遍历棋盘的途径总数,0为无法遍历一次。
Sample
Inputcopy Outputcopy 1 5 4 0 0 32
#include<stdio.h>
#include<string.h>
int t, n, m, x, y, cnt,book[10][10];
int next[8][2] = { {-1,-2},{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2} };
void dfs(int x, int y,int step)
{int tx, ty;if (step==n*m){cnt++;return;}for (int i = 0; i < 8; i++){tx = x + next[i][0];ty = y + next[i][1];if (tx<0 || ty<0 || tx>=n || ty>=m) continue;if (book[tx][ty] == 0){book[tx][ty] = 1;dfs(tx, ty,step+1);book[tx][ty] = 0;}}return;
}
int main()
{scanf("%d", &t);while (t--){cnt = 0; //因为多次输入, 所以要把步数置为0memset(book, 0, sizeof(book)); //把标记数组也置为0scanf("%d %d %d %d",&n,&m,&x,&y);book[x][y] = 1; dfs(x, y, 1); //起始步数为1printf("%d\n", cnt);}return 0;
}
Q - 红与黑
与G题一模一样, 而且就只有一组输入数据, 甚至更简单了.
XUPT 寒假算法集训第三周相关推荐
- XUPT 寒假算法集训第二周
A - 金银岛 某天KID利用飞行器飞到了一个金银岛上,上面有许多珍贵的金属,KID虽然更喜欢各种宝石的艺术品,可是也不拒绝这样珍贵的金属.但是他只带着一个口袋,口袋至多只能装重量为w的物品.岛上金属 ...
- XUPT 寒假算法集训第一周
A - 连续数的和 给你一个整数nn,你需要找到两个整数ll和rr,它们的范围是: -10^18 ≤l<r≤10^18 并且使得 l + (l + 1) +... + (r - 1) + r = ...
- 思特奇杯·云上蓝桥 -算法 集训营第二周
思特奇杯·云上蓝桥 -算法 集训营第二周 1. 带分数 题目描述 解法一 解题思路 python代码 2. 李白打酒 题目描述 解法一 解题思路 python代码 3. 第 39 级台阶 题目描述 解 ...
- 【采访】腾讯社交广告高校算法大赛第三周周冠军——到底对不队比赛经验及心得分享
[采访]腾讯社交广告高校算法大赛第三周周冠军--到底对不队比赛经验及心得分享 经过又一周紧张又激烈的角逐 腾讯社交广告高校算法大赛产生了第三周周冠军 他们的名字叫"到底对不队" 这 ...
- 腾讯广告算法大赛 | 第三周周冠军心得分享
腾讯广告算法大赛第三周周冠军出炉! 他们就是- 等等,这位帅哥如此眼熟? 没错,就是去年的总冠军队伍!! 大腿抱紧!看上届冠军为你指点迷津! 大家好,我们是来自南京大学的"每天队员都想改一次 ...
- 令人头秃的集训第三周学习记录(练习题+感悟)
永动WA题机der学习摘录 (一)经典内容(课堂) 问题一:打印n个数的全排列,共n!个 Sample Input Sample Output 代码 问题一de延伸:<五星填数> Samp ...
- 小a与204(牛客寒假算法集训营1题目B)
链接:https://ac.nowcoder.com/acm/contest/317/B 来源:牛客网 时间限制:C/C++ 1秒, 其他语言2秒 空间限制: C/C++ 262144K,其他语言52 ...
- 2023牛客寒假算法集训营3
(数学场真折磨人) A. 不断减损的时间(贪心) 题意: 给定一个数组,任意次操作,每次操作可以 选择一个偶数除以 222 . 求最终数组所有元素之和的最小值. 思路: 要使得所有元素之和最小,那肯定 ...
- 2022牛客寒假算法基础集训营6 签到题5题(附基础集训营4-6签到题总结)
1.I-A+B问题 模拟,类似于高精度,竖式运算 #include<bits/stdc++.h> using namespace std; typedef long long LL; in ...
最新文章
- 致物理学家的一个实验
- mysql数据库配置文件my.ini
- macos 10.15 django2.2+apache2.4+ladon+wsgi写webseverice接口
- Matlab自定义函数的五种方法
- OJ和PTA常见的错误代码含义
- 每日一记之数据库事务
- 【信息系统项目管理师】重点整理:高项知识地图
- 计算机专业期末总结200字,本学期自我总结200字
- 蚂蚁上市招股书:员工持股40%月薪人均5万,直奔财富自由
- SIM7600模块固件升级(模块自身升级)
- 计算机毕业设计Java计算机培训管理(源码+系统+mysql数据库+lw文档)
- 皮卡洞察报告2021版——附下载链接
- ITRON同步和通信管理
- 签证上的mult是什么意思_美国签证页上面英文表示的是什么意思?
- 轻量应用服务器阿里云和腾讯云哪个好?
- 从 Eligibility 浅谈英中翻译消除歧义的重要性
- 2017 未来科学大奖揭晓:施一公、潘建伟、许晨阳获奖
- 正版Xshell+Xftp免费使用,你还在找破解版吗
- python4.30每周一练
- 广播、组播 socket编程