备战蓝桥杯 Day1

目录

1256:献给阿尔吉侬的花束

1253:抓住那头牛

1360:奇怪的电梯(lift)

1199:全排列

1317:【例5.2】组合的输出


1256:献给阿尔吉侬的花束

【题目描述】

阿尔吉侬是一只聪明又慵懒的小白鼠,它最擅长的就是走各种各样的迷宫。今天它要挑战一个非常大的迷宫,研究员们为了鼓励阿尔吉侬尽快到达终点,就在终点放了一块阿尔吉侬最喜欢的奶酪。现在研究员们想知道,如果阿尔吉侬足够聪明,它最少需要多少时间就能吃到奶酪。

迷宫用一个R×C的字符矩阵来表示。字符S表示阿尔吉侬所在的位置,字符E表示奶酪所在的位置,字符#表示墙壁,字符.表示可以通行。阿尔吉侬在1个单位时间内可以从当前的位置走到它上下左右四个方向上的任意一个位置,但不能走出地图边界。

【输入】

第一行是一个正整数T(1 ≤ T ≤ 10),表示一共有T组数据。

每一组数据的第一行包含了两个用空格分开的正整数R和C(2 ≤ R, C ≤ 200),表示地图是一个R×C的矩阵。

接下来的R行描述了地图的具体内容,每一行包含了C个字符。字符含义如题目描述中所述。保证有且仅有一个S和E。

【输出】

对于每一组数据,输出阿尔吉侬吃到奶酪的最少单位时间。若阿尔吉侬无法吃到奶酪,则输出“oop!”(只输出引号里面的内容,不输出引号)。每组数据的输出结果占一行。

【输入样例】

3
3 4
.S..
###.
..E.
3 4
.S..
.E..
....
3 4
.S..
####
..E.

【输出样例】

5
1
oop!
#include<iostream>
#include<queue>
using namespace std;
const int N = 2e2 + 10;
char g[N][N];
bool vis[N][N];
int dx[] = { 0,0,1,-1 };
int dy[] = { 1,-1,0,0 };
int t;
int n,m,sx, sy, tx, ty;
int ans;
struct point { int x; int y; int depth; };
void bfs(point s)
{
	queue<point>q;
	q.push(s); vis[s.x][s.y] = 1;
	while (!q.empty())
	{
		point cur = q.front(); q.pop();
		if (cur.x == tx && cur.y == ty)
		{
			ans = cur.depth-1;
			return;
		}
		for (int i = 0; i < 4; i++)
		{
			int bx = cur.x + dx[i], by = cur.y + dy[i];
			if (bx<1 || bx> n || by<1 || by>m) continue;
			if (vis[bx][by]) continue;
			if (g[bx][by]=='#') continue;
			vis[bx][by] = 1;
			q.push({ bx, by,cur.depth+1 });
		}
	}
	
}

int main()
{
	cin >> t;
	while (t--)
	{
		cin >> n >> m;
		for (int i = 1; i <= n; i++)
		{
			for (int j = 1; j <= m; j++)
			{
				cin >> g[i][j];
				if (g[i][j] == 'S')sx = i, sy = j;
				if (g[i][j] == 'E')tx = i, ty = j;
			}
		}
		ans = -1;
		memset(vis, 0, sizeof vis);
		bfs({ sx, sy,1 });
		if (ans == -1)
			cout << "oop!" << endl;
		else
			cout << ans << endl;
	}
	return 0;
}

1253:抓住那头牛

【题目描述】

农夫知道一头牛的位置,想要抓住它。农夫和牛都位于数轴上,农夫起始位于点N(0≤N≤100000)�(0≤�≤100000),牛位于点K(0≤K≤100000)�(0≤�≤100000)。农夫有两种移动方式:

1、从X�移动到X−1�−1或X+1�+1,每次移动花费一分钟

2、从X移动到2×X2×�,每次移动花费一分钟

假设牛没有意识到农夫的行动,站在原地不动。农夫最少要花多少时间才能抓住牛?

【输入】

两个整数,N�和K�。

【输出】

一个整数,农夫抓到牛所要花费的最小分钟数。

【输入样例】

5 17

【输出样例】

4

#include<iostream>
#include<queue>
using namespace std;
const int N = 1e5 + 10;
char g[N];
bool vis[N];
int s, t, b;
int ans;
struct point { int x; int depth; };	
int d[] = { 1,-1,2 };
void bfs(point p)
{
	queue<point>q;
	q.push(p); vis[p.x] = 1;
	while (!q.empty())
	{
		point cur = q.front(); q.pop();
		if (cur.x == t)
		{
			ans = cur.depth-1;
			return;
		}

		for (int i = 0; i < 3; i++)
		{
            //特判*2的路径
			if(i<2)  b = cur.x + d[i];
			else  b = cur.x *d[i];
			if (b<0 || b>1e5 ) continue;
			if (vis[b]) continue;
			vis[b] = 1;
			q.push({ b,cur.depth+1 });
		}
	}
}

int main()
{
	cin >> s >> t;
	bfs({ s,1 });
	cout << ans;
	return 0;
}

1360:奇怪的电梯(lift)

【题目描述】

大楼的每一层楼都可以停电梯,而且第i层楼(1≤i≤N)(1≤�≤�)上有一个数字Ki(0≤=Ki≤=N)��(0≤=��≤=�)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如:3 3 1 2 5代表了Ki(K1=3,K2=3,……)��(�1=3,�2=3,……),从一楼开始。在一楼,按“上”可以到44楼,按“下”是不起作用的,因为没有−2−2楼。那么,从A�楼到B�楼至少要按几次按钮呢?

【输入】

共有二行,第一行为三个用空格隔开的正整数,表示N,A,B(1≤N≤200,1≤A,B≤N)�,�,�(1≤�≤200,1≤�,�≤�),第二行为N�个用空格隔开的正整数,表示Ki��。

【输出】

一行,即最少按键次数,若无法到达,则输出−1−1。

【输入样例】

5 1 5
3 3 1 2 5

【输出样例】

3
#include<iostream>
#include<queue>
using namespace std;
const int N = 2e2 + 10;
char g[N];
bool vis[N];
int n, a, b;
int ans=-1;
struct point { int x; int depth; };	
int a1[N];
void bfs(point p)
{
	queue<point>q;
	q.push(p); vis[p.x] = 1;
	while (!q.empty())
	{
		point cur = q.front(); q.pop();
		if (cur.x == b)
		{
			ans = cur.depth-1;
			return;
		}
		//向前向后移动分开判定
		int nxt1 = cur.x + a1[cur.x], nxt2 = cur.x - a1[cur.x];
		if (nxt1 >= 1 && nxt1 <= n && !vis[nxt1]) {
			vis[nxt1] = 1;
			q.push({ nxt1,cur.depth + 1 });
		}
		if (nxt2 >= 1 && nxt2 <= n && !vis[nxt2]) {
			vis[nxt2] = 1;
			q.push({ nxt2,cur.depth + 1 });
		}

	}
}

int main()
{
	cin >> n >> a >> b;
	for (int i = 1; i <= n; i++)
		cin >> a1[i];//相当于方向数组
	bfs({ a,1 });
	cout << ans;
	return 0;
}

1199:全排列

【题目描述】

给定一个由不同的小写字母组成的字符串,输出这个字符串的所有全排列。

我们假设对于小写字母有‘a’ <‘b’ < ... <‘y’<‘z’,而且给定的字符串中的字母已经按照从小到大的顺序排列。

【输入】

只有一行,是一个由不同的小写字母组成的字符串,已知字符串的长度在1到6之间。

【输出】

输出这个字符串的所有排列方式,每行一个排列。要求字母序比较小的排列在前面。字母序如下定义:

已知S=s1s2...sk,T=t1t2...tk�=�1�2...��,�=�1�2...��,则S<T等价于,存在p(1<=p<=k),使得s1=t1,s2=t2,...,sp−1=tp−1,sp<tp�1=�1,�2=�2,...,��−1=��−1,��<��成立。

【输入样例】

abc

【输出样例】

abc
acb
bac
bca
cab
cba

1317:【例5.2】组合的输出

【题目描述】

排列与组合是常用的数学方法,其中组合就是从n个元素中抽出r个元素(不分顺序且r≤n),我们可以简单地将n个元素理解为自然数1,2,…,n,从中任取r个数。

现要求你用递归的方法输出所有组合。

例如n=5,r=3,所有组合为:

1 2 3   1 2 4   1 2 5   1 3 4   1 3 5   1 4 5   2 3 4   2 3 5   2 4 5   3 4 5

【输入】

一行两个自然数n、r(1<n<21,1≤r≤n)。

【输出】

所有的组合,每一个组合占一行且其中的元素按由小到大的顺序排列,每个元素占三个字符的位置,所有的组合也按字典顺序。

【输入样例】

5 3

【输出样例】

  1  2  3
  1  2  4
  1  2  5
  1  3  4
  1  3  5
  1  4  5
  2  3  4
  2  3  5
  2  4  5
  3  4  5
#include<iostream>
using namespace std;
string s;
const int N = 1e2 + 10;
bool vis[N];
char cnt[N];
//搜索与回溯算法的模板
void dfs(int depth) {
	//5.终止条件
	if (depth > s.size()) {
		//打印原则:搜多少打多少
		for (int i = 1; i < depth; i++) cout << cnt[i];
		cout << endl;
		return;
	}
	//1.枚举方案
	for (int i = 0; i < s.size(); i++) {
		//2.标记-防止重复搜索
		if (!vis[i]) {
			//3.搜索
			vis[i] = 1;
			cnt[depth] = s[i];
			dfs(depth + 1);
			//4.回溯
			vis[i] = 0;
		}
	}
}
int main() {
	cin >> s;
	dfs(1);
	return 0;
}

#include<iostream>
using namespace std;
//n选r问题的组合
int n,r;
const int N = 1e2 + 10;
bool vis[N];
int cnt[N];
//搜索与回溯算法的组合模板
void dfs(int depth) {
	//5.终止条件
	if (depth > r) {
		//打印原则:搜多少打多少
		for (int i = 1; i < depth; i++) printf("%3d",cnt[i]);
		cout << endl;
		return;
	}
	//1.枚举方案
	for (int i = 1; i <= n;i++) {
		//2.标记-防止重复搜索
		if (!vis[i]&&i>cnt[depth-1]) {//保证无重复,也就是字典序升序,当前搜的比上一层大
			//3.搜索
			vis[i] = 1;
			cnt[depth] = i;
			dfs(depth + 1);
			//4.回溯
			vis[i] = 0;
		}
	}
}
int main() {
	cin >> n >> r;//从字符串s中选r个进行全排列
	dfs(1);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

了一li

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值