题目链接:https://vjudge.net/problem/POJ-2688
题意:在一个地面上,有一个扫地机器人,有一些障碍物,有一些脏的地砖,问,机器热能不能清扫所有的地砖,
(机器人不能越过障碍物),如果能,需要得到机器人移动最少步数。
思路:可以把扫地机器人和地砖编号,然后得出编号之间的相互距离,那么就变成了一个图问题。
用bfs来得出编号之间的距离。
再用dfs来填边,得到最少移动步数,注意要剪支,不然就T了。。。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 #include <map> 7 #include <cmath> 8 #include <iomanip> 9 using namespace std; 10 11 typedef long long LL; 12 #define inf (1LL << 25) 13 #define rep(i,j,k) for(int i = (j); i <= (k); i++) 14 #define rep__(i,j,k) for(int i = (j); i < (k); i++) 15 #define per(i,j,k) for(int i = (j); i >= (k); i--) 16 #define per__(i,j,k) for(int i = (j); i > (k); i--) 17 18 const int N = 30; 19 int mv_x[] = {0,0,1,-1}; 20 int mv_y[] = {1,-1,0,0}; 21 char mp[N][N]; 22 int sign[N][N]; 23 bool vis[N][N]; 24 bool vvv[N]; 25 int head[N]; 26 int cnt;//链式前向星 27 int go; 28 int num; 29 int ans; 30 int n,m; 31 32 struct Edge{ 33 34 int to; 35 int w; 36 int next; 37 38 }edge[1000]; 39 40 struct node{ 41 int x,y,cost; 42 node(){} 43 node(int a,int b,int c){ 44 x = a; 45 y = b; 46 cost = c; 47 } 48 }; 49 50 void add(int u,int v,int w){ 51 52 edge[cnt].to = v; 53 edge[cnt].w = w; 54 edge[cnt].next = head[u]; 55 head[u] = cnt++; 56 } 57 58 inline bool check(int x,int y){ 59 return x >= 1 && x <= n && y >= 1 && y <= m; 60 } 61 62 void bfs(int x,int y,int u){ 63 64 rep(i,1,n) rep(j,1,m) vis[i][j] = false; 65 66 queue<node > que; 67 que.push(node{ x, y, 0 }); 68 vis[x][y] = true; 69 70 while(!que.empty()){ 71 72 node tmp = que.front(); 73 que.pop(); 74 75 rep__(p,0,4){ 76 int dx = tmp.x + mv_x[p]; 77 int dy = tmp.y + mv_y[p]; 78 79 if(check(dx,dy) && !vis[dx][dy] && mp[dx][dy] != 'x'){ 80 81 vis[dx][dy] = true; 82 node in(dx, dy, tmp.cost + 1); 83 que.push(in); 84 if(sign[dx][dy] != 0){ 85 int v = sign[dx][dy]; 86 add(u,v,in.cost); 87 } 88 } 89 } 90 } 91 92 } 93 94 void dfs(int now,int W,int cnt){ 95 96 if(W > ans) return; //剪支 97 if(cnt == num){ 98 ans = min(ans, W); 99 } 100 else{ 101 102 for(int o = head[now]; ~o; o = edge[o].next){ 103 int v = edge[o].to; 104 int w = edge[o].w; 105 106 if(vvv[v]) continue; 107 108 vvv[v] = true; 109 dfs(v,W + w,cnt + 1); 110 vvv[v] = false; 111 } 112 } 113 } 114 115 int main(){ 116 117 ios::sync_with_stdio(false); 118 cin.tie(0); 119 120 while(cin >> m >> n){ 121 if(n == 0 && m == 0) break; 122 123 rep(i,1,n) rep(j,1,m) sign[i][j] = 0; //标记初始化 124 cnt = 0;//边数初始化 125 num = 0;//编号初始化 126 rep(i,1,N - 1) head[i] = -1; //头初始化 127 128 rep(i,1,n) rep(j,1,m){ 129 cin >> mp[i][j]; 130 if(mp[i][j] == 'o' || mp[i][j] == '*') sign[i][j] = ++num; //编号 131 if(mp[i][j] == 'o') go = sign[i][j]; //起始点 132 } 133 134 rep(i,1,n) rep(j,1,m){ 135 if(sign[i][j] != 0) bfs(i,j,sign[i][j]); 136 } 137 138 // rep__(i,1,N){ 139 // if(head[i] != -1){ 140 // cout << i << "--->:" << endl; 141 142 // for(int o = head[i]; ~o ; o = edge[o].next){ 143 // cout << edge[o].to << " " << edge[o].w << endl; 144 // } 145 // } 146 // } 147 148 vvv[go] = true; 149 ans = inf; 150 dfs(go,0,1); 151 vvv[go] = false; 152 153 if(ans == inf) cout << -1 << endl; 154 else cout << ans << endl; 155 } 156 157 getchar(); getchar(); 158 return 0; 159 }