Problem 2186 小明的迷宫
Accept: 45 Submit: 138
Time Limit: 1000 mSec Memory Limit : 32768 KB
Problem Description
小明误入迷宫,塞翁失马焉知非福,原来在迷宫中还藏着一些财宝,小明想获得所有的财宝并离开迷宫。因为小明还是学生,还有家庭作业要做,所以他想尽快获得所有财宝并离开迷宫。
Input
有多组测试数据。
每组数据第一行给出两个正整数n,m(0<n,m<=100)。代表迷宫的长和宽。
接着n行,每行m个整数。正数代表财宝(财宝的个数不超过10);负数代表墙,无法通过;0代表通道。
每次移动到相邻的格子,所花费的时间是1秒。小明只能按上、下、左、右四个方向移动。
小明的初始位置是(1,1)。迷宫的出口也在(1,1)。
Output
输出获得所有财宝并逃出迷宫所花费的最小时间,如果无法完成目标则输出-1。
Sample Input
3 3
0 0 0
0 100 0
0 0 0
2 2
1 1
1 1
0 0 0
0 100 0
0 0 0
2 2
1 1
1 1
Sample Output
44
思路:先求出任意两个宝藏之间的最短路,然后进行dp,dp[i][S]表示当前在i个宝藏,已经访问的宝藏集合为S的最小时间
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
typedef long long LL;
const int MAXN=105;
const int MAXM=110;
const int MAXNODE=25010;
const int MOD=1000000;
const int INF=0x3f3f3f3f;
typedef pair<int,int> pii;
int move[4][2]= {1,0,0,1,-1,0,0,-1};
int N,M,K,a[MAXN][MAXN],dis[MAXN][MAXN],dist[MAXN][MAXN];
int dp[15][2500];
bool vis2[MAXN][MAXN];
struct Point
{
int x,y;
} p[15];
int DFS(int x,int s)
{
int& ans=dp[x][s];
if(ans!=-1) return ans;
if(s+1==(1<<K)) return ans=dist[0][x];
ans=INF;
for(int i=0; i<K; i++) if(!(s&(1<<i))&&dist[i][x]!=INF)
{
int ret=DFS(i,s|(1<<i));
if(ret!=INF) ans=min(ans,ret+dist[i][x]);
}
return ans;
}
int get_dist(int sx,int sy,int ex,int ey)
{
memset(dis,0,sizeof(dis));
memset(vis2,0,sizeof(vis2));
queue<Point> q;
q.push((Point)
{
sx,sy
});
vis2[sx][sy]=1;
while(!q.empty())
{
Point tmp=q.front();
q.pop();
int x=tmp.x,y=tmp.y;
if(x==ex&&y==ey) return dis[x][y];
for(int i=0; i<4; i++)
{
int X=x+move[i][0],Y=y+move[i][1];
if(X>0&&X<=N&&Y>0&&Y<=M&&a[X][Y]>=0&&!vis2[X][Y])
{
vis2[X][Y]=1;
dis[X][Y]=dis[x][y]+1;
q.push((Point)
{
X,Y
});
}
}
}
return INF;
}
int main()
{
while(scanf("%d%d",&N,&M)!=EOF)
{
K=0;
for(int i=1; i<=N; i++)
for(int j=1; j<=M; j++)
{
scanf("%d",&a[i][j]);
if(i==1&&j==1||a[i][j]>0) p[K++]=(Point)
{
i,j
};
}
if(a[1][1]<0)
{
printf("-1\n");
continue;
}
for(int i=0; i<K; i++)
for(int j=i; j<K; j++) dist[i][j]=dist[j][i]=get_dist(p[i].x,p[i].y,p[j].x,p[j].y);
memset(dp,-1,sizeof(dp));
int ans=DFS(0,1);
if(ans==INF) printf("-1\n");
else printf("%d\n",ans);
}
return 0;
}