题意 :
给你一个迷宫,最多有四个所需要拿走的物品, 要求你从起点出发,花费最小的路程取得K个物品。问这个最小路程是多少
思路:
因为是要去取物品,然后就会有一个路程(权值),那么就可以用最短路算法来做,做到一半的时候会发现,如果要以单源最短路来做的话,就需要跑K次的最短路,因为你每拿到一件物品,你的起点就会改变。所以说我选择folry(不知道是不是这个单词 = =)因为K最多为4 , 最坏的情况下也就是4^3 的复杂度。 然后求出任意两点的最短路后,就DFS一下的事,求从起点出发,经过K个点后所取得的最小权值即为答案。
#include<iostream>
#include<cstring>
#include<queue>
#include<cmath>
#include<cstdio>
using namespace std;
const int maxn = 105 ;
char arr[105][105] ;
int n , m , coun , cnt = 0 ;
int mpt[105][105] ;
int ans = 0 ;
int vis[maxn][maxn] = {0};
int line[10] ;
int dx[] = {0,0,1,-1} ;
int dy[]= {1,-1,0,0} ;
struct node{
int x , y ;
int cost ;
};
void fory(int x){
for(int k = 0 ; k <= x ; k++)
for(int i = 0 ; i<= x ; i++)
for(int j = 0 ; j <= x ; j++)
mpt[i][j] = min(mpt[i][k] + mpt[k][j] , mpt[i][j]) ;
for(int i = 0 ; i <= x ; i++) mpt[i][i] = 0x3f ;
}
queue<node> q ;
void init(){
coun = 0 ;ans = 999999 ;
cnt = 0;
memset(mpt , 0x3f , sizeof(mpt)) ;
memset(line , 0 , sizeof(line)) ;
memset(arr , 0 , sizeof(arr)) ;
memset(vis , 0 , sizeof(vis)) ;
}
int BFS(int x , int y , int sx , int sy){
while(!q.empty()) q.pop() ;
node s1 , s2 , s3 ;
s1.cost = 0 , s1.x = x , s1.y = y ;
vis[x][y] = 0 ;
q.push(s1) ;
while(!q.empty()){
s2 = q.front() ; q.pop() ;
int xx = s2.x , yy = s2.y ;
for(int i = 0 ; i < 4 ; i++){
int xxx = xx + dx[i] ;
int yyy = yy + dy[i] ;
if(xxx < n && xxx >= 0 && yyy < m && yyy >= 0 && vis[xxx][yyy] == 0 && arr[xxx][yyy] != '#'){
vis[xxx][yyy] = 1 ;
s3.cost = s2.cost + 1 ; s3.x = xxx , s3.y = yyy ;
q.push(s3) ;
if(xxx == sx && yyy == sy) return coun = s3.cost ;
}
}
}
return -1 ;
}
void DFS(int x , int cost , int k , int tot ){
line[x] = 1 ;
if(tot == k ) ans = min(ans , cost) ;
for(int i = 0 ; i <= k ; i++){
if(line[i] == 0 && i != x){
DFS(i , mpt[x][i] + cost , k , tot + 1) ;
line[i] = 0 ;
}
}
}
int main(){
while(scanf("%d %d",&n,&m) != EOF){
if(n + m == 0) break ;
int key = 0 ;
init() ;
int AX = -1 , AY = -1 ;
for(int i = 0 ; i <n ; i++){
scanf("%s",&arr[i]) ;
for(int j = 0 ; j < m ; j++){
if(AX != -1 && AY != -1) break ;
if(arr[i][j] == '@') AX = i , AY = j ;
}
}
int k , x[10] , y[10];
cin >> k ;
for(int i = 1 ; i <= k ; i++){
scanf("%d %d",&x[i],&y[i]) ;
for(int j = 1 ; j < i ; j++){
coun = 0 ;
memset(vis , 0 , sizeof(vis)) ;
if(BFS(x[i]-1 , y[i]-1 , x[j] - 1,y[j] - 1) == -1 ) mpt[i][j] = mpt[j][i] = 0x3f ;
else {
mpt[i][j] = coun ;
mpt[j][i] =coun ;
}
}
}
for(int i = 1 ; i <= k ; i++){
memset(vis , 0 , sizeof(vis)) ;
coun = 0 ;
if(BFS(x[i] -1 , y[i]-1 , AX , AY) == -1 ) key = 1 ;
else {
mpt[0][i] = mpt[i][0] = coun ;
}
}
if(key == 1) cout << "-1" << endl ;
else {
fory(k) ;
memset(line , 0 , sizeof(line)) ;
DFS(0 , 0 , k + 1 ,1) ;
cout << ans << endl ;
}
}
return 0 ;
}
/*
4 3
#@#
...
.#.
.#.
4
2 1
2 3
4 1
4 3
*/