hdu 3681 Prison Break

http://acm.hdu.edu.cn/showproblem.php?pid=3681

题意:一个n*m的矩阵,'F'是起点。机器人从F出发,走到G可以充电,走到Y关掉开关,D不能走进,要求把所有开关关掉,且电量最少,并求出该最小电量。

把F,G,Y的坐标存起来,然后用bfs求出它们每两个点最短距离,然后用dp判断是不是可以满足目的状态。 用二分枚举答案。

  1 #include <cstdio>

  2 #include <queue>

  3 #include <cstring>

  4 #include <algorithm>

  5 #define maxn 17

  6 using namespace std;

  7 const int inf=1<<29;

  8 

  9 char g[16][16];

 10 int n,m;

 11 int gg[16][16];

 12 bool vis[16][16];

 13 int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};

 14 int sx,sy;

 15 int spos;

 16 int epos;

 17 int cnt;

 18 int dis[16][16];

 19 int dp[(1<<maxn)][maxn];

 20 struct node

 21 {

 22     int x,y;

 23 }p[16],st,st1,st2;

 24 

 25 int bfs(int s,int t)

 26 {

 27     queue<node>q;

 28     memset(vis,false,sizeof(vis));

 29     for(int i=0; i<n; i++)

 30     {

 31         for(int j=0; j<m; j++)

 32         {

 33             dis[i][j]=inf;

 34         }

 35     }

 36     dis[p[s].x][p[s].y]=0;

 37     st.x=p[s].x;

 38     st.y=p[s].y;

 39     vis[p[s].x][p[s].y]=true;

 40     q.push(st);

 41     while(!q.empty())

 42     {

 43         st1=q.front();

 44         q.pop();

 45         if(st1.x==p[t].x&&st1.y==p[t].y)

 46         {

 47             return dis[st1.x][st1.y];

 48         }

 49         for(int i=0; i<4; i++)

 50         {

 51             int xx=st1.x+dir[i][0];

 52             int yy=st1.y+dir[i][1];

 53             if(xx>=0&&xx<n&&yy>=0&&yy<m&&!vis[xx][yy]&&g[xx][yy]!='D')

 54             {

 55                 dis[xx][yy]=dis[st1.x][st1.y]+1;

 56                 st2.x=xx;

 57                 st2.y=yy;

 58                 vis[xx][yy]=true;

 59                 q.push(st2);

 60             }

 61         }

 62     }

 63     return -1;

 64 }

 65 

 66 int ok(int c)

 67 {

 68     memset(dp,-1,sizeof(dp));

 69     dp[1<<spos][spos]=c;

 70     for(int i=0; i<(1<<cnt); i++)

 71     {

 72         for(int j=0; j<cnt; j++)

 73         {

 74             if((i&(1<<j))==0) continue;

 75             if(dp[i][j]==-1) continue;

 76             if((i&epos)==epos) return true;

 77             for(int k=0; k<cnt; k++)

 78             {

 79                 if(i&(1<<k)) continue;

 80                 if(gg[j][k]==-1) continue;

 81                 if(dp[i][j]<gg[j][k]) continue;

 82                 if(dp[i|(1<<k)][k]==-1) dp[i|(1<<k)][k]=dp[i][j]-gg[j][k];

 83                 else dp[i|(1<<k)][k]=max(dp[i|(1<<k)][k],dp[i][j]-gg[j][k]);

 84                 int x1=p[k].x,y1=p[k].y;

 85                 if(g[x1][y1]=='G') dp[i|(1<<k)][k]=c;

 86             }

 87         }

 88     }

 89     return false;

 90 }

 91 

 92 int main()

 93 {

 94     while(scanf("%d%d",&n,&m)!=EOF)

 95     {

 96         if(n==0&&m==0) break;

 97         cnt=0;

 98         epos=0;

 99         for(int i=0; i<n; i++)

100         {

101             scanf("%s",g[i]);

102             for(int j=0; j<m; j++)

103             {

104                 if(g[i][j]=='F')

105                 {

106                     sx=i; sy=j;

107                     spos=cnt;

108                     epos|=(1<<cnt);

109                     p[cnt].x=i;

110                     p[cnt++].y=j;

111                 }

112                 if(g[i][j]=='G')

113                 {

114                     p[cnt].x=i;

115                     p[cnt++].y=j;

116                 }

117                 if(g[i][j]=='Y')

118                 {

119                     epos|=(1<<cnt);

120                     p[cnt].x=i;

121                     p[cnt++].y=j;

122                 }

123             }

124         }

125         for(int i=0; i<cnt; i++)

126         {

127             for(int j=0; j<cnt; j++)

128             {

129                 if(i==j) gg[i][j]=0;

130                 else gg[i][j]=bfs(i,j);

131             }

132         }

133         int l=0,r=n*m;

134         int mid;

135         int ans=-1;

136         while(l<=r)

137         {

138             mid=(l+r)>>1;

139             if(ok(mid))

140             {

141                 ans=mid;

142                 r=mid-1;

143             }

144             else l=mid+1;

145         }

146         printf("%d\n",ans);

147     }

148     return 0;

149 }
View Code

 

你可能感兴趣的:(break)