题目意思 :
大概是这个意思 给你一个N*M的地图 地图中存在一些信息 ‘#’表示不能通过的路段 ‘.’表示可以通过的路 ‘@’表示起始点
然后给你n个点 和这些点的坐标 问题大概是求一个 遍历了所有点的最短路 如果没有这样一条路 输出-1;
首先用 dfs 或者 全排列 的思路大概是 首先把这些特殊点和初始点 全都放在一起 然后找到任意两点之间的距离 没错 就是这样
刚开始我想到找到任意距离之后 用最小生成树 解决问题 后来发现 这个是没有办法用最小生成树的 因为他不具备这种性质
当然也可以用状态压缩 这种方法可以解决当特殊点比较多的情况 而这种情况是深搜不容易解决的
先贴一个深搜做的 全排列的做法跟这个几乎一样 不写了
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
#include <cmath>
using namespace std;
const int N = 105;
int n, m;
int ans;
struct Node
{
int x, y;
int steps;
};
int tar_nums , stx , sty;
Node tar_pos[5];
char Map[N][N];
int s[4];
int idx[N][N];
int bfs(int start, int End)
{
Node a = tar_pos[start];
a.steps = 0;
queue<Node>q;
q.push(a);
memset(idx , 0, sizeof(idx));
idx[a.x][a.y] = 1;
while (!q.empty()) {
Node temp;
temp = a = q.front();q.pop();
if(a.x == tar_pos[End].x && a.y == tar_pos[End].y) {
return a.steps;
}
int dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1}};
for (int i = 0; i < 4; i ++) {
int xx = a.x + dir[i][0];
int yy = a.y + dir[i][1];
if(xx > 0 && xx <= n && yy > 0 && yy <= m && !idx[xx][yy] && Map[xx][yy] != '#') {
idx[xx][yy] = 1;
a.steps ++;
a.x = xx,a.y = yy;
q.push(a);
}
a = temp;
}
}
return -1;
}
int dis[6][6];
void dfs(int x , int from , int sum)
{
if(x == tar_nums) {
ans = min(ans , sum);
}
for (int i = 1; i <= tar_nums; i ++) {
if(!s[i]) {
s[i] = 1;
dfs(x + 1, i , sum + dis[from][i]);
s[i] = 0;
}
}
}
int main()
{
while (cin >> n >> m && (n + m)) {
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= m; j ++) {
cin >> Map[i][j];
if(Map[i][j] == '@') {
stx = i, sty = j;
}
}
cin >> tar_nums;
tar_pos[0].x = stx , tar_pos[0].y = sty;
for (int i = 1; i <= tar_nums ; i ++) {
cin >> tar_pos[i].x >> tar_pos[i].y;
}
bool flag = true;
for (int i = 0; i <= tar_nums; i ++) {
for (int j = i ; j <= tar_nums; j ++) {
if(i == j) dis[i][j] = 0;
else {
int temp = bfs(i , j);
if(temp == -1) {flag = false ; cout << i << " " << j << endl; break;}
dis[i][j] = dis[j][i] = temp;
}
}if(!flag)break;
}
if(!flag) {
cout << -1 << endl;continue;
}
memset(s , 0, sizeof(s));
ans = 0x7fffffff;
dfs(0 , 0 , 0);
cout << ans << endl;
}
}
再贴一份 用状态压缩写的
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 105;
struct Node
{
int x, y, state;
};
Node Points[5];
int n , m, stx, sty, num_points;
char Map[maxn][maxn];
int idx[1 << 4][maxn][maxn];
int dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1}};
int Bfs()
{
Node start;
start.x = stx, start.y = sty, start.state = 0;
for (int i = 0; i < num_points; i ++) {
if(start.x == Points[i].x && start.y == Points[i].y) {
start.state = 0 | (1 << i);break;
}
}
memset(idx , 0, sizeof(idx));
idx[start.state][start.x][start.y] = 1;
queue<Node>q;
q.push(start);
while (!q.empty()) {
Node temp = start = q.front(); q.pop();
if(temp.state == (1 << num_points) - 1) {
return idx[temp.state][temp.x][temp.y] - 1;
}
// printf("state == %d\n", (1 << num_points) - 1);
for (int i = 0; i < 4; i ++) {
start.x = temp.x + dir[i][0];
start.y = temp.y + dir[i][1];
for (int i = 0; i < num_points; i ++) {
if(start.x == Points[i].x && start.y == Points[i].y) {
start.state = start.state | (1 << i);break;
}
}
if(start.x >= 1 && start.y >= 1 && start.x <= n && start.y <= m
&& !idx[start.state][start.x][start.y] && Map[start.x][start.y] != '#') {
idx[start.state][start.x][start.y] = idx[temp.state][temp.x][temp.y] + 1;
q.push(start);
}
start = temp;
}
}
return -1;
}
int main()
{
while (~scanf("%d%d",&n,&m) && (n + m)) {
getchar();
for (int i = 1; i <= n; i ++) {
for (int j = 1; j <= m; j ++) {
scanf("%c",&Map[i][j]);
if(Map[i][j] == '@')
stx = i, sty = j;
}getchar();
}
scanf("%d",&num_points);
for (int i = 0; i < num_points; i ++) {
scanf("%d%d",&Points[i].x, &Points[i].y);
}
printf("%d\n",Bfs());
}
return 0;
}
/*
4 4
#@##
....
....
....
3
2 1
2 4
3 1
*/