题意:
给你一个迷宫,和几个宝藏点, 只有 ‘.’ 能走,‘@’是起点,求把所有宝藏都拿到的最小步数。 如果不能全部拿到,输出-1。
思路:
最开始以为深搜记录能过,但是后来才发现先到达宝藏的先后顺序也会影响步数,这是在工程听课,做的一道题,听学长讲的思路是:
分别以各个宝藏和起点为开始广搜到达各个地方的步数,记录下来, 由于宝藏个数数据量很小,所以只需要对经过的顺序进行一个全排列,然后求总和最小的一条路。
Code:
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<stack>
#include<bitset>
#include<set>
#include<map>
#include<vector>
#define LL long long
#define See(a) cout << #a << " = " << a << endl;
#define rep(i, s, e) for(int i = (s); i <= (e); ++i)
#define drep(i, s, e) for(int i = (s); i >= (e); --i)
#define debug(a, s, e) rep(_i, s, e) { cout << a[_i] << ' ';} cout << endl;
#define debug2(a, s, e, ss, ee) { rep(i_, s, e) {debug(a[i_], ss, ee);}}
using namespace std;
const int N = 105;
const int INF = 2e9;
int n, m, t;
char a[N][N];
bool v[N][N];
int f[10][10];
int r[10][2];
int mv[4][2] = {
1, 0,
0, 1,
-1, 0,
0, -1
};
struct Node
{
int x, y, tep;
Node(int tep = 0):tep(tep){}
Node(int _x, int _y, int _tep):
x(_x), y(_y), tep(_tep){}
}st, to;
void bfs(int sx, int sy, int u)
{
queue<Node> Q;
st = Node(sx, sy, 0);
Q.push(st);
int x, y;
while(!Q.empty())
{
st = Q.front();Q.pop();
x = st.x;
y = st.y;
rep(i, 0, t)
{
if(x == r[i][0] && y == r[i][1])
{
f[u][i] = st.tep;
// printf("f[%d][%d] = %d\n", u, i, f[u][i]);
}
}
rep(i, 0, 3)
{
x = st.x + mv[i][0];
y = st.y + mv[i][1];
if(!v[x][y] && a[x][y] != '#' && a[x][y])
{
v[x][y] = true;
to = Node(x, y, st.tep + 1);
Q.push(to);
}
}
}
}
int main()
{
// freopen("in.txt", "r", stdin);
while(~scanf("%d%d", &n, &m))
{
if(n == 0 && m == 0)
{
return 0;
}
memset(a, 0, sizeof(a));
memset(f, -1, sizeof(f));
rep(i, 0, 6)
{
f[i][i] = 0;
}
int sx, sy;
getchar();
rep(i, 1, n)
{
rep(k, 1, m)
{
scanf("%c", &a[i][k]);
if(a[i][k] == '@')
{
sx = i;
sy = k;
}
}
getchar();
}
scanf("%d", &t);
int x, y;
r[0][0] = sx;
r[0][1] = sy;
rep(i, 1, t)
{
scanf("%d%d", &r[i][0], &r[i][1]);
// a[r[i][0]][r[i][1]] = '^';
}
// debug2(a, 1, n, 1, m);
rep(i, 0, t)
{
memset(v, false, sizeof(v));
v[r[i][0]][r[i][1]] = true;
bfs(r[i][0], r[i][1], i);
}
int z[] = {1, 2, 3, 4, 5};
int ans = 2e9;
// debug2(f, 0, t, 0, t);
do{
int tem = f[0][z[0]];
int p = f[0][z[0]];
if(p < 0)
{
ans = -1;
}
rep(i, 1, t - 1)
{
p = f[z[i]][z[i - 1]];
if(p < 0)
{
ans = -1;
}
tem += p;
}
if(tem < ans)
{
ans = tem;
// See(ans);
// debug(z, 0, t);
}
}while(next_permutation(z, z + t));
// See(f[4][0]);
// See(f[0][3]);
// See(f[3][2]);
// See(f[2][1]);
// See(f[4][0] + f[0][3] + f[3][2] + f[2][1]);
printf("%d\n", ans < 0 ? -1 : ans);
}
return 0;
}
有的时候问题就是这么简单,分别对各个问题进行求解, 然后再进行有机的结合就是完整的答案。