AmazingCounters.com

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 }

 

posted @ 2015-03-22 16:10  philippica  阅读(389)  评论(0编辑  收藏  举报