第五节 搜索专题 - 1

A. 可可口乐

题目描述

收完玉米之后,小 Q 感觉有些口渴。他去商店买了自己最喜欢的可口可乐。

回到家后,小 Q 眉头一皱,发现事情并不简单,因为瓶身上印着的赫然是“cococala”而不是"cocacola",也就是说他买到的是“可可口乐”。而将第二个"o"和第一个"a"交换之后,"cococala"才会变成“cocacola”。

小 Q 气坏了,他想知道自己买的这瓶饮料和真正的“cocacola”到底相差多少。

即你需要求出:输入字符串通过最少几次字母交换后才能变成“cocacola”。

输入格式

第一行一个长度为 \(8\) 的字符串,代表饮料的名字。

输出格式

输出一行一个整数,代表最少的交换次数。

样例输入

cococala

样例输出

1

数据规模

输入字符串长度为 \(8\),且保证有解。

点击查看代码
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

string t = "cocacola", s;
int ans = 8, n = 8;

void dfs(int i, int num) {
	if(num >= ans) return;
	if(i == n) {
		ans = num;
		return; 
	}
	for(int j = i; j < n; j ++) {
		if(s[j] == t[i]) {
			swap(s[i], s[j]);
			dfs(i + 1, num + (i != j));
			swap(s[i], s[j]);
		}
	}
}

int main() {
	cin >> s;
	dfs(0, 0);
	cout << ans;
	return 0;
}
编译结果
compiled successfully
time: 2ms, memory: 3516kb, score: 100, status: Accepted
> test 1: time: 0ms, memory: 3344kb, points: 10, status: Accepted
> test 2: time: 1ms, memory: 3348kb, points: 10, status: Accepted
> test 3: time: 0ms, memory: 3516kb, points: 10, status: Accepted
> test 4: time: 0ms, memory: 3360kb, points: 10, status: Accepted
> test 5: time: 0ms, memory: 3456kb, points: 10, status: Accepted
> test 6: time: 0ms, memory: 3512kb, points: 10, status: Accepted
> test 7: time: 0ms, memory: 3460kb, points: 10, status: Accepted
> test 8: time: 1ms, memory: 3460kb, points: 10, status: Accepted
> test 9: time: 0ms, memory: 3280kb, points: 10, status: Accepted
> test 10: time: 0ms, memory: 3464kb, points: 10, status: Accepted

B. 郊游

时间:3s 空间:256M

题目描述:

同学们在教室坐好,准备去郊游,他们依次离开教室。同学们的座位由一个 \(n × n\) 的矩阵表示,左上角为下标 \((1,1)\) 的同学,右下角为 \((n,n)\),而且座位编号是从左上角到右下角一排排一列列编号的,分别为 \(1、2、3、4…… n ^ 2\) 。第i个离开教室的同学的初始座位是 \(a_i\)。当前走动的同学可以从当前位置移动到其上下左右 \(4\) 个相邻座位之一,当他走到一个非空的座位时会和坐在这个位置上的同学成为好朋友,每个同学都会选择结交最少好朋友的走法离开教室。计算所有好朋友对 \((i,j)\) 的数量 \((i≠j)\)

输入格式:

第一行包含一个整数 \(n\),表示矩阵大小。

接下来一行包含 \(n × n\) 个整数,表示依次离开的同学的初始座位 。

输出格式:

输出一个整数表示答案。

样例1输入:

3
5 2 4 6 8 1 3 7 9

样例1输出:

1

样例2输入:

3
2 5 4 6 8 1 3 7 9

样例2输出:

0

样例3输入:

4
6 7 1 4 13 16 10 9 5 11 12 14 15 2 3 8

样例3输出:

3

约定与提示:

对于 \(100\%\) 的数据,\(2 \le n \le 500\)\(1 \le a_i \le n × n\)
样例1和2的座位如图:

1 2 3
4 5 6
7 8 9

样例1解释:坐在5号座位的同学先离开教室,他必须经过1,2,3,4,6,7,8,9座位中的一个,所以他必须跟其中1个同学成为朋友。

样例2解释:坐在2号座位的同学先离开教室,接着坐在5号座位的同学离开,他可以经过2号座位离开教室。

样例3的座位如图:

1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
点击查看代码
#include<iostream>
#include<algorithm>
#include<vector>
#include<string.h>
#include<queue>
using namespace std;

#define int long long
#define MAXN 505
int n, ans = 0;
bool b[MAXN][MAXN], vis[MAXN][MAXN];
int dx[4] = { -1, 0, 1, 0 };
int dy[4] = { 0, -1, 0, 1 };
int mp[MAXN][MAXN], a[MAXN][MAXN];

void dfs(int x, int y){
    for(int i = 0; i < 4; i ++){
        int nx = x + dx[i];
        int ny = y + dy[i];
        if(nx >= 1 && nx <= n && ny >= 1 && ny <= n && !vis[nx][ny]){
            if(mp[nx][ny] > mp[x][y] + b[x][y]){
                vis[nx][ny] = true;
                mp[nx][ny] = mp[x][y] + b[x][y];
                dfs(nx, ny);
                vis[nx][ny] = false;
            }
        }
    }
}
signed main(){
    cin >> n;
    memset(b, 1, sizeof b);
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= n; j ++)
            mp[i][j] = min(min(i - 1, j - 1), min(n - i, n - j));
    for(int i = 1; i <= n; i ++){
        for(int j = 1; j <= n; j ++){
            cin >> a[i][j];
            memset(vis, 0, sizeof vis);
            int x = (a[i][j] + n - 1) / n, y = a[i][j] - (x - 1) * n;
            ans += mp[x][y];
            b[x][y] = false;
            vis[x][y] = true;
            dfs(x, y);
        }
    }
    cout << ans;
    return 0;
}
编译结果
compiled successfully
time: 11677ms, memory: 23120kb, score: 100, status: Accepted
> test 1: time: 78ms, memory: 6096kb, points: 4, status: Accepted
> test 2: time: 244ms, memory: 6692kb, points: 4, status: Accepted
> test 3: time: 2514ms, memory: 23120kb, points: 4, status: Accepted
> test 4: time: 1ms, memory: 5832kb, points: 4, status: Accepted
> test 5: time: 1ms, memory: 5828kb, points: 4, status: Accepted
> test 6: time: 1ms, memory: 5932kb, points: 4, status: Accepted
> test 7: time: 1ms, memory: 4000kb, points: 4, status: Accepted
> test 8: time: 2ms, memory: 3952kb, points: 4, status: Accepted
> test 9: time: 1ms, memory: 4048kb, points: 4, status: Accepted
> test 10: time: 4ms, memory: 4128kb, points: 4, status: Accepted
> test 11: time: 3ms, memory: 3980kb, points: 4, status: Accepted
> test 12: time: 4ms, memory: 4000kb, points: 4, status: Accepted
> test 13: time: 11ms, memory: 4096kb, points: 4, status: Accepted
> test 14: time: 114ms, memory: 4980kb, points: 4, status: Accepted
> test 15: time: 121ms, memory: 4892kb, points: 4, status: Accepted
> test 16: time: 366ms, memory: 5780kb, points: 5, status: Accepted
> test 17: time: 1727ms, memory: 8020kb, points: 5, status: Accepted
> test 18: time: 1603ms, memory: 7976kb, points: 5, status: Accepted
> test 19: time: 1624ms, memory: 7956kb, points: 5, status: Accepted
> test 20: time: 1609ms, memory: 7956kb, points: 5, status: Accepted
> test 21: time: 1646ms, memory: 8024kb, points: 5, status: Accepted
> test 22: time: 1ms, memory: 5860kb, points: 5, status: Accepted
> test 23: time: 1ms, memory: 5884kb, points: 5, status: Accepted

C. 黑白路径

时间:1s 空间:256M

题目描述:

有一个 \(n × m\) 的矩阵,矩阵中有两种颜色:黑('#'),白('.')

小信选了一个黑色位置 \(s\),坐标为 \((x_s, y_s)\)。当小信移动时,他可以往 \(4\) 个方向(上下左右)行进,但还有一个要求:假设当前小信从 \((x_1, y_1)\) 出发,他之后停下的位置坐标为 \((x_2, y_2)\),要求 \((x_1, y_1)\)\((x_2, y_2)\) 的颜色不同。

最终小信会在白色位置 \(t\) ,坐标为 \((x_t, y_t)\) 停下。

请问有多少对 \((s,t)\) 可以从 \(s\) 走到 \(t\)

输入格式:

第一行包含两个整数 \(n\), \(m\)

接下来包含一个 \(n × m\) 的矩阵

输出格式:

输出一个整数表示答案。

样例1输入:

4 3
###
###
...
###

样例1输出:

6

样例2输入:

3 3
.#.
..#
#..

样例2输出:

10

约定与提示:

对于 \(100\%\) 的数据,\(1 \le n,m \le 400\)

对于样例1:其中一条路径为 \((2,1)\) -> \((3,1)\)

点击查看代码
#include<iostream>
#include<algorithm>
#include<vector>
#include<string.h>
#include<queue>
#include<stack>
#include<set>
using namespace std;

#define int long long
#define MAXN 405 
char mp[MAXN][MAXN];
int n, m, a, b, ans;
int dx[4] = { 1, 0, -1, 0 };
int dy[4] = { 0, -1, 0, 1 };
bool vis[MAXN][MAXN];

void dfs(int x, int y) {
	if(vis[x][y]) return;
	vis[x][y] = true;
	if(mp[x][y] == '.') b ++;
	else a ++;
	for(int i = 0; i < 4; i ++) {
		int xx = x + dx[i], yy = y + dy[i];
		//printf("(%d, %d) -> (%d, %d)\n", x, y, xx, yy);
		if(xx > 0 && xx <= n && yy > 0 && yy <= m && mp[xx][yy] != mp[x][y]) dfs(xx, yy);
	}
	return;
}
signed main() {
	cin >> n >> m;
	for(int i = 1; i <= n; i ++)
		for(int j = 1; j <= m; j ++)
			cin >> mp[i][j];
	for(int i = 1; i <= n; i ++)
		for(int j = 1; j <= m; j ++) {
			a = 0, b = 0;
			dfs(i, j);
			ans += a * b;
		}
	cout << ans;
	return 0;
}
编译结果
compiled successfully
time: 146ms, memory: 16204kb, score: 100, status: Accepted
> test 1: time: 0ms, memory: 3468kb, points: 1, status: Accepted
> test 2: time: 1ms, memory: 3216kb, points: 1, status: Accepted
> test 3: time: 0ms, memory: 3444kb, points: 4, status: Accepted
> test 4: time: 0ms, memory: 3400kb, points: 4, status: Accepted
> test 5: time: 1ms, memory: 3404kb, points: 4, status: Accepted
> test 6: time: 0ms, memory: 3504kb, points: 4, status: Accepted
> test 7: time: 0ms, memory: 3356kb, points: 4, status: Accepted
> test 8: time: 0ms, memory: 3432kb, points: 4, status: Accepted
> test 9: time: 1ms, memory: 3372kb, points: 4, status: Accepted
> test 10: time: 1ms, memory: 3368kb, points: 4, status: Accepted
> test 11: time: 1ms, memory: 3412kb, points: 4, status: Accepted
> test 12: time: 0ms, memory: 3392kb, points: 4, status: Accepted
> test 13: time: 9ms, memory: 3764kb, points: 4, status: Accepted
> test 14: time: 11ms, memory: 3676kb, points: 4, status: Accepted
> test 15: time: 9ms, memory: 3692kb, points: 4, status: Accepted
> test 16: time: 8ms, memory: 3736kb, points: 4, status: Accepted
> test 17: time: 11ms, memory: 3680kb, points: 4, status: Accepted
> test 18: time: 11ms, memory: 3684kb, points: 4, status: Accepted
> test 19: time: 10ms, memory: 3732kb, points: 4, status: Accepted
> test 20: time: 9ms, memory: 3684kb, points: 4, status: Accepted
> test 21: time: 10ms, memory: 3684kb, points: 4, status: Accepted
> test 22: time: 10ms, memory: 3680kb, points: 4, status: Accepted
> test 23: time: 11ms, memory: 3684kb, points: 4, status: Accepted
> test 24: time: 11ms, memory: 3672kb, points: 4, status: Accepted
> test 25: time: 6ms, memory: 3764kb, points: 3, status: Accepted
> test 26: time: 6ms, memory: 3776kb, points: 3, status: Accepted
> test 27: time: 9ms, memory: 16204kb, points: 4, status: Accepted

D. 上学

题目描述

鱼大大就读的学校每天都有检查出勤的楷(e)模(xin)学委。刚巧这天鱼大大起床迟了一些,为了不被这些楷(e)模(xin)学委记录扣分,鱼大大需要挑一条距离最短的小路上学。

身为鱼大大的好朋友,你深知鱼大大的苦楚:鱼大大这个小短腿,每次迈步都只能往上下左右走一格,而学校又在距离鱼大大家直线距离最远的地方(学校在 (n,m) ),要是不好好规划肯定会迟到。于是你便自告奋勇在鱼大大起床刷牙吃早饭的时候,在地图上帮鱼大大选出一条最快到达学校的路程,并告诉鱼大大这条路的距离以及路线。


注:鱼大大的家在地图左上角 \((1,1)\)。起点不算入路径长度

地图上的 \(#\) 为坑,会会掉进去,也跨不过去,不能走。

地图大小为 \(N * M\)

输入格式

第一行两个整数 \(N\)\(M\) (\(1 < N, M \le 1000\))

接下来N行,每行M个字符,表示鱼大大能否通过相应位置的区域。字符只可能是 \(.\)\(#\)

\(.\) 表示鱼大大可以走的路。

\(#\) 表示鱼大大不能跨过的坑。

输出格式

第一行一个整数表示路径长度

接下来若干行,每行包含两个用空格隔开的整数,表示鱼大大依次通过的区域的坐标。

如果无法到达学校,输出 \(-1\)

(若是有多条最短路径,输出其中任何一条即可)

输入样例

5 8
..#...##
#.#.#.##
#...#...
#.#.#.#.
....#.#.

输出样例

15
1 1
1 2
2 2
3 2
3 3
3 4
2 4
1 4
1 5
1 6
2 6
3 6
3 7
3 8
4 8
5 8
点击查看代码
#include<iostream>
#include<algorithm>
#include<vector>
#include<string.h>
#include<queue>
#include<stack>
using namespace std;

#define MAXN 1005
struct node {
	int qx, qy, num;
} b[MAXN][MAXN];
int n, m, a[MAXN][MAXN], l[MAXN], r[MAXN];
char mp[MAXN][MAXN];
bool vis[MAXN][MAXN];
int dx[4] = { 0, -1, 0, 1 };
int dy[4] = { 1, 0, -1, 0 };
stack<node> s;

void bfs(int x, int y) {
	queue<node> q;
	q.push({x, y, 0});
	a[x][y] = q.front().num;
	vis[x][y] = true;
	while(!q.empty()) {
		for(int i = 0; i < 4; i ++) {
			node p = q.front();
			int xx = p.qx + dx[i], yy = p.qy + dy[i];
			if(xx <= n && xx >= 1 && yy <= m && yy >= 1 && mp[xx][yy] == '.' && !vis[xx][yy]) {
				a[xx][yy] = p.num + 1;
				q.push({xx, yy, a[xx][yy]});
				if(!b[xx][yy].qx && !b[xx][yy].qy) b[xx][yy].qx = p.qx, b[xx][yy].qy = p.qy;
				vis[xx][yy] = true;
			}
		}
		q.pop();
	}
}

int main() {
	cin >> n >> m;
	for(int i = 1; i <= n; i ++) 
		for(int j = 1; j <= m; j ++)
			cin >> mp[i][j];
	bfs(1, 1);
	if(!a[n][m]) { cout << -1 << endl; return 0; }
	else cout << a[n][m] << endl;
	int xx = n, yy = m;
	while(true) {
		if(xx == 0 && yy == 0) break;
		s.push({xx, yy, 0});
		int xxx = xx;
		xx = b[xx][yy].qx, yy = b[xxx][yy].qy;
	}
	//cout << sum - 2 << endl;
	while(!s.empty()) {
		cout << s.top().qx << " " << s.top().qy << endl;
		s.pop();
	}
	
//	for(int i = 1; i <= n; i ++) {
//		for(int j = 1; j <= m; j ++) {
//			printf("(%d, %d) ", b[i][j].qx, b[i][j].qy);
//		}
//		cout << endl;
//	}
	
	return 0;
}
编译结果
compiled successfully
time: 154ms, memory: 21032kb, score: 100, status: Accepted
> test 1: time: 1ms, memory: 5508kb, points: 10, status: Accepted
> test 2: time: 1ms, memory: 5584kb, points: 10, status: Accepted
> test 3: time: 0ms, memory: 5432kb, points: 10, status: Accepted
> test 4: time: 1ms, memory: 7860kb, points: 10, status: Accepted
> test 5: time: 1ms, memory: 8048kb, points: 10, status: Accepted
> test 6: time: 0ms, memory: 7952kb, points: 10, status: Accepted
> test 7: time: 1ms, memory: 7636kb, points: 10, status: Accepted
> test 8: time: 37ms, memory: 18460kb, points: 10, status: Accepted
> test 9: time: 46ms, memory: 18768kb, points: 10, status: Accepted
> test 10: time: 66ms, memory: 21032kb, points: 10, status: Accepted

E. 锻炼身体的路径

Time Limit: 1000ms Memory Limit: 262144kb

题目描述

题目描述:

有一个 \(n × m\) 的地图,空地为 '.',高楼为 '#',小信的家在 'S'。

小信想找一条锻炼身体的路径,路径需要从家出发,不经过相同的空地,最后回到家。出于锻炼身体的目的,这条路径的长度必须至少为 \(4\),也就是说除了终点和起点都是家以外,经过的不同的空地个数至少为 \(3\)

小信想知道这样的路径存不存在。当然,小信无法通过有高楼的地方,所以可能不存在这样的路径。

输入格式

第一行包含两个整数 \(n, m\)

接下来包含一个 \(n × m\) 的地图,地图只包含 '.','#','S' 三种字符。

输出格式

如果存在锻炼身体的路径,输出 "Yes",否则输出 "No"。

样例

Input 1

4 4
....
#.#.
#S#.
....

Output 1

Yes

Input 2

4 4
.#..
#.#.
#S#.
....

Output 2

No

数据范围

对于 \(100\%\) 的数据,\(2 ≤ n,m ≤ 10^6\)\(4 ≤ n · m ≤ 10^6\)

点击查看代码
#include<iostream>
#include<algorithm>
#include<vector>
#include<string.h>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;

int dx[4] = { 1, -1, 0, 0 };
int dy[4] = { 0, 0, -1, 1 };
int n, m, x, y;
map<int, map<int, bool> > mp;
map<int, map<int, int> > flag;
void dfs(int x, int y, int xd, int yd, int res) { 
    if(x == xd && y == yd && res)
        if(res >= 4){ cout << "Yes\n"; exit(0); }
		else return;
	if(res && res <= flag[x][y]) return;
    else flag[x][y] = res;
    for(int i = 0; i < 4; i ++) {
        int xx = x + dx[i], yy = y + dy[i];
        if(xx >= 1 && xx <= n && yy >= 1 && yy <= m && mp[xx][yy]) {
            mp[xx][yy] = false;
			//printf("(%d, %d) -> (%d, %d)  %d\n", x, y, xx, yy, res);
            dfs(xx, yy, xd, yd, res + 1);
            mp[xx][yy] = true;
        }
    }
    return;
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> m;
    for(int i = 1; i <= n; i ++) {
        for(int j = 1; j <= m; j ++) {
            char s;
            cin >> s;
            if(s == 'S') x = i, y = j, mp[i][j] = true;
            else if(s == '#') mp[i][j] = false;
            else mp[i][j] = true;
        }
    }
    dfs(x, y, x, y, 0);
    cout<<"No\n";
    return 0;
}
编译结果
compiled successfully
time: 2874ms, memory: 145584kb, score: 100, status: Accepted
> test 1: time: 0ms, memory: 3468kb, points: 4, status: Accepted
> test 2: time: 1ms, memory: 3380kb, points: 4, status: Accepted
> test 3: time: 151ms, memory: 50712kb, points: 4, status: Accepted
> test 4: time: 129ms, memory: 50196kb, points: 4, status: Accepted
> test 5: time: 156ms, memory: 50820kb, points: 4, status: Accepted
> test 6: time: 141ms, memory: 50296kb, points: 4, status: Accepted
> test 7: time: 210ms, memory: 50992kb, points: 4, status: Accepted
> test 8: time: 129ms, memory: 50428kb, points: 4, status: Accepted
> test 9: time: 147ms, memory: 50528kb, points: 4, status: Accepted
> test 10: time: 155ms, memory: 50724kb, points: 4, status: Accepted
> test 11: time: 0ms, memory: 3540kb, points: 4, status: Accepted
> test 12: time: 1ms, memory: 3372kb, points: 4, status: Accepted
> test 13: time: 1ms, memory: 3532kb, points: 4, status: Accepted
> test 14: time: 243ms, memory: 50252kb, points: 4, status: Accepted
> test 15: time: 476ms, memory: 145584kb, points: 4, status: Accepted
> test 16: time: 139ms, memory: 51548kb, points: 4, status: Accepted
> test 17: time: 114ms, memory: 37044kb, points: 4, status: Accepted
> test 18: time: 50ms, memory: 22052kb, points: 4, status: Accepted
> test 19: time: 106ms, memory: 28940kb, points: 4, status: Accepted
> test 20: time: 103ms, memory: 40256kb, points: 4, status: Accepted
> test 21: time: 103ms, memory: 31228kb, points: 5, status: Accepted
> test 22: time: 64ms, memory: 23068kb, points: 5, status: Accepted
> test 23: time: 148ms, memory: 36960kb, points: 5, status: Accepted
> test 24: time: 107ms, memory: 39604kb, points: 5, status: Accepted
posted @ 2023-07-14 19:54  So_noSlack  阅读(392)  评论(0)    收藏  举报