第五节 搜索专题 - 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
本文来自博客园,作者:So_noSlack,转载请注明原文链接:https://www.cnblogs.com/So-noSlack/p/17554874.html