1140:Cleaning Robot

問題文
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1140&lang=jp








































幅優先探索でスタート位置と汚れについて全点対間最短距離を求めておいて、パスを全部試す。

#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
#include<queue>

#define INF 100000000
#define x first
#define y second
#define f first
#define s second

using namespace std;

typedef pair<int,int>P;
typedef pair<P,int>P3;

string grid[20];
int g[11][11],cost[21][21],h,w;
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
vector<P>v;

void bfs(P st,int id){
	
	queue<P3>que;
	que.push(P3(st,0));
	while(!que.empty()){
		P3 now=que.front();
		que.pop();
		if(cost[now.f.y][now.f.x]<=now.s)continue;
		
		cost[now.f.y][now.f.x]=now.s;
	
		if(grid[now.f.y][now.f.x]=='*')
			for(int i=0;i<v.size();i++)
				if(v[i]==now.f)g[id][i]=now.s;
		
		for(int i=0;i<4;i++){
			int nx=now.f.x+dx[i],ny=now.f.y+dy[i];
			if(nx<0 || ny<0 || w<=nx || h<=ny || grid[ny][nx]=='x')continue;
			que.push(P3(P(nx,ny),now.s+1));
		}
	}
}

int main(void){
	
	while(cin >> w >> h,h|w){
		
		for(int i=0;i<h;i++)cin >> grid[i];
		fill(g[0],g[11],INF);
		v.clear();
		P st;
		for(int i=0;i<h;i++){
			for(int j=0;j<w;j++){
				if(grid[i][j]=='o')st.x=j,st.y=i,v.push_back(st);
				if(grid[i][j]=='*')v.push_back(P(j,i));
			}
		}
		
		for(int i=0;i<v.size();i++){
			fill(cost[0],cost[21],INF);
			bfs(v[i],i);
		}
		
		vector<P3>tmp;
		int stid;
		for(int i=0;i<v.size();i++){
			if(v[i]!=st)tmp.push_back(P3(v[i],i));
			else if(v[i]==st)stid=i;
		}
		
		sort(tmp.begin(),tmp.end());
		int ans=INF;
		do{
			int cnt=0;
			for(int i=0;i<tmp.size()-1;i++)cnt+=g[tmp[i].s][tmp[i+1].s];
			ans=min(ans,g[stid][tmp[0].s]+cnt);
		}while(next_permutation(tmp.begin(),tmp.end()));
		
		if(ans>=INF)cout << -1 << endl;
		else cout << ans << endl;
	}
	return 0;
}