Consider the room floor paved with square tiles whose size fits the cleaning robot (1 * 1). There are ‘clean tiles’ and ‘dirty tiles’, and the robot can change a ‘dirty tile’ to a ‘clean tile’ by visiting the tile. Also there may be some obstacles (furniture) whose size fits a tile in the room. If there is an obstacle on a tile, the robot cannot visit it. The robot moves to an adjacent tile with one move. The tile onto which the robot moves must be one of four tiles (i.e., east, west, north or south) adjacent to the tile where the robot is present. The robot may visit a tile twice or more.
Your task is to write a program which computes the minimum number of moves for the robot to change all ‘dirty tiles’ to ‘clean tiles’, if ever possible.
Input
w h
c11 c12 c13 … c1w
c21 c22 c23 … c2w
…
ch1 ch2 ch3 … chw
The integers w and h are the lengths of the two sides of the floor of the room in terms of widths of floor tiles. w and h are less than or equal to 20. The character cyx represents what is initially on the tile with coordinates (x, y) as follows.
‘.’ : a clean tile
‘*’ : a dirty tile
‘x’ : a piece of furniture (obstacle)
‘o’ : the robot (initial position)
In the map the number of ‘dirty tiles’ does not exceed 10. There is only one ‘robot’.
The end of the input is indicated by a line containing two zeros.
Output
Sample Input
7 5
.......
.o...*.
.......
.*...*.
.......
15 13
.......x.......
...o...x....*..
.......x.......
.......x.......
.......x.......
...............
xxxxx.....xxxxx
...............
.......x.......
.......x.......
.......x.......
..*....x....*..
.......x.......
10 10
..........
..o.......
..........
..........
..........
.....xxxxx
.....x....
.....x.*..
.....x....
.....x....
0 0
Sample Output
8
49
-1
题意:
- 给一张n列m行的图
- o代表扫地机器人
- *代表垃圾
- .代表空地
- x代表障碍
- 让你求扫地机器人最少走多少步能将所有垃圾清扫(机器人只能上下左右一次一格)
- 因为这是一个直观的点图,而两点之间的直线距离与曼哈顿距离是正相关的,所以我们可以简单地将这些点之间的距离看作直线距离
- 两点之间线段最短,也就是说,当我们要从A到B时,我们不能借助任何的C使得A到B的距离变短
- 所以在其中的任意一个状态,我们都只会直接走向下一个有效点。
- 所以整个问题就转化为了一个TSP问题(哈密尔顿通路)
- 具体做法是
- bfs找到任意两个有效点(o、*为有效点)之间的最短距离。
- dfs求所有点走完后的最短距离。
- 不过一想到TSP…遗传算法?模拟退火?
-
//#include<bits/stdc++.h> #include<algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cassert> #include <cstdio> #include <vector> #include <string> #include <cmath> #include <queue> #include <stack> #include <set> #include <map> using namespace std; #define P(a,b,c) make_pair(a,make_pair(b,c)) #define rep(i,a,n) for (int i=a;i<=n;i++) #define per(i,a,n) for (int i=n;i>=a;i--) #define CLR(vis) memset(vis,0,sizeof(vis)) #define MST(vis,pos) memset(vis,pos,sizeof(vis)) #define pb push_back #define mp make_pair #define all(x) (x).begin(),(x).end() #define fi first #define se second #define SZ(x) ((int)(x).size()) typedef pair<int,pair<int,int> >pii; typedef long long ll; typedef unsigned long long ull; const ll mod = 1000000007; const int INF = 0x3f3f3f3f; ll gcd(ll a, ll b) { return b ? gcd(b, a%b) : a; } template<class T>inline void gmax(T &A, T B) { (A<B)&&(A=B);//if(B>A)A=B; } template<class T>inline void gmin(T &A, T B) { (A>B)&&(A=B);//if(B<A)A=B; } template <class T> inline bool scan_d(T &ret) { char c; int sgn; if(c=getchar(),c==EOF) return 0; //EOF while(c!='?'&&(c<'0'||c>'9')) c=getchar(); sgn=(c=='?')?-1:1; ret=(c=='?')?0:(c-'0'); while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0'); ret*=sgn; return 1; } inline void outt(int x) { if(x>9) outt(x/10); putchar(x%10+'0'); } const int MAXN = 1e6+10; int n,m,num,ans; char g[30][30]; int d[30][30]; bool vis[30][30]; bool Vis[1000]; pair<int,int>p[1000]; int robot; int dir[4][2]= {{-1,0},{1,0},{0,-1},{0,1}}; struct node { int x; int y; int cnt; node(int _x=0,int _y=0,int _cnt=0):x(_x),y(_y),cnt(_cnt) {} }; queue<node>q; int bfs(int S,int T) { int t_x=p[T].fi,t_y=p[T].se; int s_x=p[S].fi,s_y=p[S].se; CLR(vis); vis[s_x][s_y]=1; while(!q.empty())q.pop(); q.push(node(s_x,s_y,0)); while(!q.empty()) { node tmp=q.front(); q.pop(); int x=tmp.x,y=tmp.y,cnt=tmp.cnt; if(x==t_x&&y==t_y)return cnt; rep(i,0,3) { int xx=x+dir[i][0],yy=y+dir[i][1]; if(xx<=n&&xx>0&&yy<=m&&yy>0&&!vis[xx][yy]&&g[xx][yy]!='x') { vis[xx][yy]=1; q.push(node(xx,yy,cnt+1)); } } } return INF; } void dfs(int cnt,int len,int x) { if(cnt==num&&len<ans) { ans=len; return; } if(len>=ans)return; rep(y,1,num) { if(!Vis[y]) { Vis[y]=1; dfs(cnt+1,len+d[x][y],y); Vis[y]=0; } } } int main() { while(scanf("%d%d", &m,&n)&&m&&n) { num=0; rep(i,1,n) { scanf("%s", g[i]+1); rep(j,1,m) { if(g[i][j]=='*'||g[i][j]=='o') { p[++num].fi=i,p[num].se=j; if(g[i][j]=='o')robot=num; } } } int flag=1; rep(i,1,num) { d[i][i]=0; rep(j,i+1,num) { d[i][j]=d[j][i]=bfs(i,j); if(d[i][j]==INF) { puts("-1"); flag=0; break; } } if(!flag)break; } if(flag) { ans=INF; CLR(Vis); Vis[robot]=1; dfs(1,0,robot); printf("%d\n",ans==INF?-1:ans); } } return 0; } /* 7 5 ....... .o...*. ....... .*...*. ....... 15 13 .......x....... ...o...x....*.. .......x....... .......x....... .......x....... ............... xxxxx.....xxxxx ............... .......x....... .......x....... .......x....... ..*....x....*.. .......x....... 10 10 .......... ..o....... .......... .......... .......... .....xxxxx .....x.... .....x.*.. .....x.... .....x.... 0 0 8 49 -1 */