HDU - 2354 Another Brick in the Wall (优先队列+BFS 记忆化)

After years as a brick-layer, you've been called upon to analyze the structural integrity of various brick walls built by the Tetrad Corporation. Instead
of using regular-sized bricks, the Tetrad Corporation seems overly fond of bricks made out of strange shapes. The structural integrity of a wall can be
approximated by the fewest number of bricks that could be removed to create a gap from the top to the bottom. Can you determine that number for
various odd walls created by Tetrad?
Input
Input to this problem will begin with a line containing a single integer X (1 ≤ X ≤ 100) indicating the number of data sets. Each data set consists of
two components:

A single line, "M N" (1 ≤ M,N ≤ 20) where M and N indicate the height and width (in units), respectively, of a brick wall;
A series of M lines, each N alphabetic characters in length. Each character will indicate to which brick that unit of the wall belongs to. Note
that bricks will be contiguous; each unit of a brick will be adjacent (diagonals do not count as adjacent) to another unit of that brick. Multiple
bricks may use the same characters for their representation, but any bricks that use identical characters will not be adjacent to each other. All
letters will be uppercase.
Output
For each data set, output the fewest number of bricks to remove to create a gap that leads from some point at the top of the wall, to some point at the
bottom of the wall. Assume that bricks are in fixed locations and do not "fall" if bricks are removed from beneath them. A gap consists of contiguous
units of removed bricks; each unit of a gap must be adjacent (diagonals do not count) to another unit of the gap.
Sample Input
3
5 7
AABBCCD
EFFGGHH
IIJJKKL
MNNOOPP
QQRRSST
5 7
AABBCCD
AFFBGGD
IIJBKKD
MNNOOPD
QQRRSST
6 7
ABCDEAB
ABCFEAB
AEAABAB
ACDAEEB
FFGAHIJ
KLMANOP
Sample Output
5
2

2

题意:给一个n*m的地图,让你从上到下敲出一条裂缝所敲裂的砖块的数量最小,怎么判断是同一块砖,当它上下左右和它的字母相同的时候,算是同一块砖。

思路:把第一层的点全部入优先队列,每次读出步数最小的点,当搜到最后一层跳出,因为是优先队列,所以首先搜到的肯定是最短路,而且标记也要改一下,因为这

块砖有可能会转弯,book数组的话要记录上次走到这个点所用的步数

#include<iostream>
#include<cstdio>
#include<functional>
#include<queue>
#include<cstring>
using namespace std;
#define N 99999999
int m,n;
int Map[25][25];
int book[25][25];
struct node{
    int x;
    int y;
    int stemp;
}u,e;
struct cmp{
    int operator()(node x,node y){
        if(x.stemp!=y.stemp)return x.stemp>y.stemp;
        else if(x.x!=y.x)return x.x>y.x;
        return x.y>y.y;
    }
};
int text(node a){
    if(a.x<0 || a.x>=n || a.y<0 || a.y >=m)
        return 0;
    return 1;
}
void BFS(){
    priority_queue<node,vector<node>,cmp>q;//定义的优先队列是node类型,用的是vector容器,按照cmp函数进行排列
    while(!q.empty()) q.pop();
    int i;
    int next[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
    for(i=0;i<m;i++){
        u.x=0;
        u.y=i;
        u.stemp=1;
        book[u.x][u.y]=1;//步数为1
        q.push(u);
     //   printf("R u.x=%d u.y=%d u.stemp=%d\n",u.x,u.y,u.stemp);

    }
    while(!q.empty()){
        u=q.top();
        q.pop();
       //  printf("C u.x=%d u.y=%d u.stemp=%d\n",u.x,u.y,u.stemp);
        if(u.x==n-1){//搜到最后一层
            printf("%d\n",u.stemp);
            break;
        }
        for(i=0;i<4;i++){
            e.x=u.x+next[i][0];
            e.y=u.y+next[i][1];
            e.stemp=u.stemp;
            if(text(e)==1){
              //  printf("Map[u.x][u.y]=%c Map[e.x][e.y]=%c\n",Map[u.x][u.y],Map[e.x][e.y]);
                 if(Map[u.x][u.y]!=Map[e.x][e.y]){//当不是一块砖步数会+1
                    e.stemp=u.stemp+1;
                 }
                 if(book[e.x][e.y]>e.stemp)//当走到走过已经走过的路,判断这次走到是否比上次走到同一个点所用的步数短
                 q.push(e);
                 book[e.x][e.y]=e.stemp;
               //   printf("R e.x=%d e.y=%d e.stemp=%d\n",e.x,e.y,e.stemp);
            }
        }
    }
}
int main(){
   int t;
   int i,j;
   scanf("%d",&t);
   while(t--){
       scanf("%d%d",&n,&m);
       getchar();
       for(i=0;i<n;i++){
         for(j=0;j<m;j++){
            scanf("%c",&Map[i][j]);
            book[i][j]=N;//初始化book数组
         }
         getchar();
       }

       BFS();
   }

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值