FZU 2186 小明的迷宫 【压状dp】
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
Sample Output
4 4
思路: 发现是一个中国邮递员问题,果断压状
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 const int dx[10]={0,0,0,1,-1},dy[10]={0,1,-1,0,0}; 7 int a[109][109],monx[100],mony[100],n,m,ma[109][109]; 8 queue<int>qans,qx,qy; 9 bool visit[109][109]; 10 int check(int x,int y){ 11 if(x<=0 || x>n || y<=0 || y>m || a[x][y]<0 || visit[x][y])return 1; 12 return 0; 13 } 14 void bfs(int x,int y,int sc) 15 { 16 memset(visit,0,sizeof(visit)); 17 int l=0,r=0;visit[x][y]=1; 18 qx.push(x);qy.push(y);qans.push(0); 19 while(!qx.empty()) 20 { 21 x=qx.front();y=qy.front(); 22 qx.pop();qy.pop(); 23 int ans=qans.front(); 24 qans.pop(); 25 for(int i=1;i<=4;i++) 26 { 27 int xx=x+dx[i],yy=y+dy[i]; 28 if(check(xx,yy))continue; 29 if(a[xx][yy]>0)ma[sc][a[xx][yy]]=ans+1; 30 visit[xx][yy]=1; 31 qx.push(xx);qy.push(yy);qans.push(ans+1); 32 } 33 } 34 } 35 int only_one(int k){ 36 if(k-(k & (-k)) == 0)return 1;return 0; 37 } 38 int dp[15][10000]; 39 int dfs2(int k,int s,int h) 40 { 41 if(dp[k][s]!=-1)return dp[k][s]; 42 if(only_one(s))return ma[k][1]; 43 int ans=0x3f3f3f3f,full = ((1<<(h))-1) ^ (1<<(k-1)); 44 for(int i=1;i<=h;i++) 45 if(i != k && ((s & ((1<<(i-1)))) !=0))ans=min(ans,dfs2(i,s & full,h) + ma[k][i]); 46 return dp[k][s]=ans; 47 } 48 int main() 49 { 50 while(scanf("%d%d",&n,&m)!=EOF) 51 { 52 memset(dp,-1,sizeof(dp)); 53 memset(ma,0x3f,sizeof(ma)); 54 int h=0,flag=0; 55 for(int i=1;i<=n;i++) 56 { 57 for(int j=1;j<=m;j++) 58 { 59 scanf("%d",&a[i][j]); 60 if(i==1 && j==1)flag=a[i][j]; 61 if(a[i][j]>0 || (i==1 && j==1))a[i][j]=++h,monx[h]=i,mony[h]=j; 62 } 63 } 64 for(int i=1;i<=h;i++)ma[i][i]=0; 65 for(int i=1;i<=h;i++)bfs(monx[i],mony[i],i); 66 if(flag<0) 67 { 68 printf("-1\n");continue; 69 } 70 int u=dfs2(1,(1<<h)-1,h); 71 if(u>=0x3f3f3f3f)u=-1; 72 printf("%d\n",u); 73 } 74 return 0; 75 }