首页 > 其他分享 >第七节 搜索专题 - 3

第七节 搜索专题 - 3

时间:2023-07-17 15:44:06浏览次数:30  
标签:status 10 专题 int 搜索 memory test 第七节 Accepted

A. 推箱子

题目描述:

推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个 \(M \times N\) 的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推箱子而不能拉箱子,因此如果箱子被推到一个角上(如图 \(2\) )那么箱子就不能再被移动了,如果箱子被推到一面墙上,那么箱子只能沿着墙移动.

现在给定房间的结构,箱子的位置,搬运工的位置和箱子要被推去的位置,请你计算出搬运工至少要推动箱子多少格.

输入格式:

输入数据的第一行是一个整数 \(T\)(\(1 \le T \le 20\)),代表测试数据的数量.然后是 \(T\) 组测试数据,每组测试数据的第一行是两个正整数 \(M\),\(N\)(\(2 \le M,N \le 7\)),代表房间的大小,然后是一个 \(M\) 行 \(N\) 列的矩阵,代表房间的布局,其中 \(0\) 代表空的地板, \(1\) 代表墙, \(2\) 代表箱子的起始位置, \(3\) 代表箱子要被推去的位置,\(4\) 代表搬运工的起始位置.

输出格式:

对于每组测试数据,输出搬运工最少需要推动箱子多少格才能帮箱子推到指定位置,如果不能推到指定位置则输出 \(-1\).

样例输入:

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

样例输出:

4

数据规模:

见题面描述。

点击查看代码
int t;
int ax,ay,bx,by,cx,cy,n,m,step;
int f[10][10][10][10],a[10][10];
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};

void dfs(int ax, int ay, int bx, int by, int cx, int cy,int step,int n,int m) {
	if(f[ax][ay][bx][by] <= step) return;
	f[ax][ay][bx][by] = step;
	if (ax == cx && ay == cy) return;
	for (int i = 0; i < 4; i++) {
		int nx = bx + dx[i], ny = by + dy[i];
		if(!(nx >= 1 && nx <= n && ny >= 1 && ny <= m && a[nx][ny] != 1)) continue;
		if(nx == ax && ny == ay){
			int tx = ax+dx[i],ty = ay+dy[i];
			if(!(tx >= 1 && tx <= n && ty >= 1 && ty <= m && a[tx][ty] != 1)) continue;
			dfs(tx,ty,nx,ny,cx,cy,step+1,n,m);
		}
		else {
			dfs(ax,ay,nx,ny,cx,cy,step,n,m);	
		}
	}
}
int main() {
	scanf("%d", &t);
	while (t--) {
		scanf("%d %d", &n, &m);
		memset(f,0x3f,sizeof(f));
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= m; j++) {
				scanf("%d", &a[i][j]);
				if (a[i][j] == 2)ax = i, ay = j;//箱子
				if (a[i][j] == 4)bx = i, by = j;//人
				if (a[i][j] == 3)cx = i, cy = j;//目标位置
			}
		}
		dfs(ax, ay, bx, by, cx, cy, 0, n, m);
		int ans = f[0][0][0][0];
		for(int i=0;i<4;i++){
			int nx = cx+dx[i],ny=cy+dy[i];
			if(1<=nx&&nx<=n&&1<=ny&&ny<=m&&a[nx][ny]!=1)
				ans = min(ans,f[cx][cy][nx][ny]);	
		}
		if(ans == f[0][0][0][0])cout<<"-1\n";
		else cout<<ans<<endl;
	}
	return 0;
}
编译结果
compiled successfully
time: 2ms, memory: 392kb, score: 100, status: Accepted
> test 1: time: 0ms, memory: 392kb, points: 10, status: Accepted
> test 2: time: 0ms, memory: 392kb, points: 10, status: Accepted
> test 3: time: 0ms, memory: 392kb, points: 10, status: Accepted
> test 4: time: 0ms, memory: 392kb, points: 10, status: Accepted
> test 5: time: 0ms, memory: 392kb, points: 10, status: Accepted
> test 6: time: 0ms, memory: 392kb, points: 10, status: Accepted
> test 7: time: 1ms, memory: 392kb, points: 10, status: Accepted
> test 8: time: 0ms, memory: 392kb, points: 10, status: Accepted
> test 9: time: 1ms, memory: 392kb, points: 10, status: Accepted
> test 10: time: 0ms, memory: 392kb, points: 10, status: Accepted

B. 迷宫难题

题目描述:

这是一个 \(n\) 行 \(m\) 列的迷宫,某些格子有若干枚钥匙。相邻格子之间有一扇门,门上有若干把锁,所有的锁都打开才能够通行,若没有锁则直接通行。对应的钥匙可以打开对应的锁,钥匙和锁的类型范围由数字 \(0\) 到 \(p\) 表示。每一步可以走到周围四连通的格子之一,门可以从两个方向打开,捡钥匙和开锁不消耗时间。问从 (\(1, 1\)) 到 (\(n, m\)) 最少需要走多少步。

输入格式:

第一行三个整数 \(n,m,p\)。

第二行一个整数 \(K\),

接下来 \(K\) 行每行 \(5\) 个整数 \(x_1, y_1, x_2, y_2, t\),表示 (\(x_1, y_1\)) 与 (\(x_2, y_2\)) 之间的门上有一把 \(t\) 类型的锁。

保证 (\(x_1, y_1\)) 与 (\(x_2, y_2\)) 相邻。

下一行一个整数 \(S\),表示钥匙的个数。

接下来 \(S\) 行每行三个整数 \(x, y, t\),表示 \(x,y\) 处有一枚 \(t\) 类型的钥匙。

输出格式:

输出一行表示答案。

样例输入:

4 4 9
9
1 2 1 3 2
1 2 2 2 0
2 1 2 2 0
2 1 3 1 0
2 3 3 3 0
2 4 3 4 1
3 2 3 3 0
3 3 4 3 0
4 3 4 4 0
2
2 1 2
4 2 1

样例输出:

14

数据规模:

\(N,M,P \le 10\), \(K < 150\), \(S \le 150\)。

点击查看代码
#define MAXN 12
queue<pair<pair<int, int>, int> > q;
int n, m, p, k, x1, x2, y3, y2, t, s, x, y, cur, ans;
bool vis[MAXN][MAXN][2050];
int gate[MAXN][MAXN][MAXN][MAXN], key[MAXN][MAXN], dis[MAXN][MAXN][2050];
int dx[] = { -1,0,1,0 };
int dy[] = { 0,1,0,-1 };

int main() {
	pair<pair<int, int>, int> cur;
	scanf("%d %d %d", &n, &m, &p);
	scanf("%d", &k);
	for (int i = 1; i <= k; i++) {
		scanf("%d %d %d %d %d", &x1, &y3, &x2, &y2, &t);
		gate[x1][y3][x2][y2] |= (1 << t);
		gate[x2][y2][x1][y3] |= (1 << t);
	}
	scanf("%d", &s);
	for (int i = 1; i <= s; i++) {
		scanf("%d %d %d", &x, &y, &t);
		key[x][y] |= (1 << t);
	}
	memset(dis, 0x3f, sizeof(dis));
	dis[1][1][key[1][1]] = 0;
	vis[1][1][key[1][1]] = true;
	q.push(make_pair(make_pair(1, 1), key[1][1]));
	while (!q.empty()) {
		cur = q.front(); q.pop();
		x = cur.first.first;
		y = cur.first.second;
		k = cur.second;
		for (int i = 0; i < 4; i++) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && (k & gate[x][y][nx][ny]) == gate[x][y][nx][ny]) {
				int nk = k | key[nx][ny];
				if (!vis[nx][ny][nk]) {
					vis[nx][ny][nk] = true;
                    dis[nx][ny][nk] = dis[x][y][k]+1;
					q.push(make_pair(make_pair(nx, ny), nk));
				}
			}
		}
	}
	ans = dis[0][0][0];
	for (int i = 0; i < (1 << 11); i++) ans = min(ans, dis[n][m][i]);
	if (ans == dis[0][0][0]) cout << "-1\n";
	else cout << ans << endl;
	return 0;
}
编译结果
compiled successfully
time: 7ms, memory: 1876kb, score: 100, status: Accepted
> test 1: time: 0ms, memory: 1876kb, points: 10, status: Accepted
> test 2: time: 0ms, memory: 1876kb, points: 10, status: Accepted
> test 3: time: 1ms, memory: 1876kb, points: 10, status: Accepted
> test 4: time: 1ms, memory: 1876kb, points: 10, status: Accepted
> test 5: time: 1ms, memory: 1876kb, points: 10, status: Accepted
> test 6: time: 1ms, memory: 1876kb, points: 10, status: Accepted
> test 7: time: 0ms, memory: 1876kb, points: 10, status: Accepted
> test 8: time: 2ms, memory: 1876kb, points: 10, status: Accepted
> test 9: time: 1ms, memory: 1876kb, points: 10, status: Accepted
> test 10: time: 0ms, memory: 1876kb, points: 10, status: Accepted

C. 大学生活

题目描述:

大学的课程是在不同教室上的,需要同学们在不同时间自己去上课。

小Q 当前位置在 \(A\),他下一门课在 \(B\) 处上,他想知道最短多少次操作才能到达 \(B\)。

一次操作可以是:朝当前方向走一步、向左转、向右转、向后转。

初始时小Q可以任选一个朝向。

输入格式:

第一行包含一个整数 \(n\),表示大学的边长。

接下来 \(n\) 行,每行一个长度为 \(n\) 的字符串。'x' 表示障碍物,'.' 表示道路。

输出格式:

输出一个整数表示答案,走不到则输出 \(-1\)。

样例输入:

3
.xA
...
Bx.

样例输出:

6

数据规模:

\(2 \le N \le 100\)。

点击查看代码
#define MAXN 105
int n, ans = -1;
int xy[4][2] = { {1, 0}, {0, 1}, {-1, 0}, {0, -1} };
char mp[MAXN][MAXN];
bool vis[MAXN][MAXN][4];
struct node{ int x, y, step, p; };
void bfs(int x,int y){
	queue<node> q;
	q.push({x, y, 0, -1});
	while(q.size()) {
		node t = q.front();
		if(mp[t.x][t.y] == 'B') {
			ans = t.step;
			return;
		}
		q.pop();
		for(int i = 0; i < 4; i ++) {
			int xx = t.x + xy[i][0], yy = t.y + xy[i][1];
			if(xx >= 1 && xx <= n && yy >= 1 && yy <= n && mp[xx][yy] != 'x' && vis[xx][yy][i] == 0) {
				if(t.p == -1 || t.p == i) {
					vis[xx][yy][i] = 1;
					q.push({xx, yy, t.step + 1, i});
				}
				else
					q.push({t.x, t.y, t.step + 1, i});
			}
		}
	}
}
int main(){
	cin >> n;
	int x, y;
	for(int i = 1; i <= n; i ++)
		for(int j = 1; j <= n; j ++) {
			cin >> mp[i][j];
			if(mp[i][j] == 'A') x = i, y = j;
		}
	bfs(x, y);
	cout << ans << endl;
	return 0;
}
编译结果
compiled successfully
time: 12ms, memory: 3600kb, score: 100, status: Accepted
> test 1: time: 0ms, memory: 3492kb, points: 10, status: Accepted
> test 2: time: 2ms, memory: 3544kb, points: 10, status: Accepted
> test 3: time: 2ms, memory: 3428kb, points: 10, status: Accepted
> test 4: time: 1ms, memory: 3420kb, points: 10, status: Accepted
> test 5: time: 1ms, memory: 3432kb, points: 10, status: Accepted
> test 6: time: 2ms, memory: 3444kb, points: 10, status: Accepted
> test 7: time: 1ms, memory: 3600kb, points: 10, status: Accepted
> test 8: time: 2ms, memory: 3440kb, points: 10, status: Accepted
> test 9: time: 0ms, memory: 3436kb, points: 10, status: Accepted
> test 10: time: 1ms, memory: 3360kb, points: 10, status: Accepted

标签:status,10,专题,int,搜索,memory,test,第七节,Accepted
From: https://www.cnblogs.com/So-noSlack/p/17559109.html

相关文章

  • Linux磁盘专题
    物理磁盘名次和其作用盘片:disk盘片上下都有磁头。磁盘面:盘片有上下两面,每一面叫磁盘面磁头:heads每个磁头负责一个磁盘面,负责读取数据、将数据写入磁道。磁头都是固定在机械臂上(机械臂就是磁头臂组支架)磁道:track每个磁盘面上围绕圆心划分出多个同心圆环,每个圆圈叫做磁......
  • Linux磁盘专题-常用分区命令
    划分分区fdisk专门用于划分MBR类型的分区。(mbr分区类型在linx中也叫msdos)注意:fdisk在centos7上已经可以用来划分gpt类型的分区。详细不说了,N年之前学习过gdisk专用与划分gpt类型分区。大致操作和fdisk一样,不记录了,N年前学过。。partedparted之前懒得学,现在看了下也是......
  • Linux磁盘专题-linux文件系统详解
    这可是我几年前的杰作笔记呀.....当初手写计算都会,现在忘光光....物理硬盘Block的概念和作用硬盘底层一次IO就是读、写一次扇区,一个扇区默认是512Byte。读写大量文件如果以扇区为单位会很慢、性能不好,所以出现了逻辑块的概念(logicblock),也就是硬盘Block。逻辑块Block是......
  • 第七节 面向对象
    知识点面向对象题目1(完成)定义手机类,手机有品牌(brand),价格(price)和颜色(color)三个属性,有打电话call()和sendMessage()两个功能。请定义出手机类,类中要有空参、有参构造方法,set/get方法。定义测试类,在主方法中使用空参构造创建对象,使用set方法赋值。调用对象的两个功能,打......
  • BST(二叉搜索树)、AVL(平衡二叉树)、RBT(红黑树)的区别
    一、二叉搜索树(BST:BinarySortTree)二叉查找树就是左结点小于根节点,右结点大于根节点的一种排序树,也叫二叉搜索树。二叉查找树比普通树查找更快,查找、插入、删除的时间复杂度为O(logN)。但是二叉查找树有一种极端的情况,就是会变成一种线性链表似的结构。此时时间复......
  • 代码随想录算法训练营第三十二天| 343. 整数拆分 96.不同的二叉搜索树
     343.整数拆分要求:将一个正数拆分成N个正整数,使得这N个正整数的乘机是最大的思路:DP数组:dp[n]N的时候,它的乘机最大值注意:不是i*dp[n-i]就是最大值,因为如果用dp就证明要开始拆分了,如果我不拆分,就是用的这两个数的话,那么就是单纯的i*(n-i)代码:1//要求:将N拆分成K......
  • chrome内核的开发者工具搜索功能的一点欠缺
    最近学习点东西,需要一些人名等数据,就想随便找lol里的人物做例子。比如:name黑暗之女--title安妮--roles法师。在英雄列表页面中可看到其name黑暗之女,但并没有显示title与roles,只有点击进入详情页面后,才能看到安妮和法师的信息。按照经验,推断即使在英雄列表也可能会有相关信息。......
  • vue+axios实现输入框多条件搜索功能
    Vue+Axios实现输入框多条件搜索功能在现代的Web开发中,搜索功能是一个非常重要的特性。用户们希望能够根据自己的需求输入多个条件来筛选出所需要的数据。Vue.js是一个流行的JavaScript框架,可以轻松地实现这样的功能。而Axios是一个基于Promise的HTTP库,可以方便地与后端进行数据......
  • 背包之专题
    P1282多米诺骨牌-洛谷|计算机科学教育新生态(luogu.com.cn)第一题一道思维题 设dis=a[i]−b[i]f[i][j+dis+N]=min(f[i][j+dis+N],f[i−1][j+N]);//不反转f[i][j+dis+N]=min(f[i][j+dis+N],f[i−1][j+N]+1);//反转f[i][j+N]=min(f[i−1][j−dis+N],f[i−1][j+dis+N]+1......
  • google引擎搜索技巧
    找歌词或忘记的句子【*】在谷歌搜索引擎中使用,代表所有可能性。如果你忘记了一段句子的某部分,可以加入*搜索,会过滤出所有可能性的句子。例如:youdon’t*me搜索完整句子【“”】如果你想要找某个东西,但是这个东西的单字都是有个别意思的,就好像巧克力蛋糕的“巧克力......