CSL的校园卡

思路:

bfs,用状压表示走过的区域,然后和x1,y1,x2,y2构成所有的状态,然后标记一下就可以了

代码:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head bool vis[(<<) + ][][][][];
int dir[][] = {, , , , , -, -, };
char s[][];
int n, m;
struct node {
int x1, y1, x2, y2, dis, st;
};
int get(int x, int y) {
return (x-)*m + y - ;
}
int bfs() {
queue<node> q;
int st = ;
for (int i = ; i <= n; i++) {
for (int j = ; j <= m; j++) {
if(s[i][j] == 'S' || s[i][j] == 'X') st |= <<get(i, j);
}
}
for (int i = ; i <= n; i++) {
for (int j = ; j <= m; j++) {
if(s[i][j] == 'S') {
q.push(node{i, j, i, j, , st});
break;
}
}
}
while(!q.empty()) {
node now = q.front();
q.pop();
if(now.st == (<<n*m) - ) return now.dis;
if(!vis[now.st][now.x1][now.y1][now.x2][now.y2]) vis[now.st][now.x1][now.y1][now.x2][now.y2] = true;
else continue;
for (int i = ; i < ; i++) {
for (int j = ; j < ; j++) {
int x = now.x1 + dir[i][];
int y = now.y1 + dir[i][];
int xx = now.x2 + dir[j][];
int yy = now.y2 + dir[j][];
if( <= x && x <= n && <= y && y <= m && <= xx && xx <= n && <= yy && yy <= m && s[x][y] != 'X' && s[xx][yy] != 'X') {
q.push(node{x, y, xx, yy, now.dis+, now.st|(<<get(x, y))|(<<get(xx, yy))});
}
}
}
}
return ;
}
int main() {
scanf("%d %d", &n, &m);
for (int i = ; i <= n; i++) {
scanf("%s", s[i]+);
}
printf("%d\n", bfs());
return ;
}
05-04 07:28