zoukankan      html  css  js  c++  java
  • P1141 01迷宫

    题目描述:

      传送门

    思路:

      标准的宽搜过7个点,TLE3个点,那么如何进行优化:
      在bfs中优化比较少,这里卡点的原因是多次的起点输入导致需要多次进行bfs(而且题目给出的次数上限竟然为100000)不卡你才怪呢,所以我们可以采取一种类似于打表的方法,对迷宫所有坐标都搜一遍。但实际上会有很多重复的bfs,因此每次bfs的时候都进行flag的标记点,标记相同的代表处于同一个连通图上(同一个连通图是互相任意可达的,故连通图上的点的结果相同,都是连通图点的数量)。因此后面要搜的点若在已经生成的连通图上时,就没必要再bfs而是直接根据flag标记的值直接输出,从而达到了类似于打表的效果。注意:不同连通图上的标记值不同,为了方便后面输出结果(标记值相同的点,结果一样)
     
    代码:
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<queue>
     4 #include<string.h>
     5 #include<algorithm>
     6 using namespace std;
     7 #define re register
     8 
     9 typedef pair<int,int> P;
    10 int n,m;
    11 int mapp[1005][1005];        //存迷宫 
    12 int flag[1005][1005];        //标记        不同连通图上的标记值不同 
    13 int sx[100005],sy[100005];    //起点和终点 
    14 int dx[4]={0,1,0,-1};
    15 int dy[4]={1,0,-1,0};
    16 int ans[100000000];            //储存结果 尽量开的大一些 
    17 int bfs(int x,int y,int t){
    18     int sum=0;                //记录步数 
    19     queue<P> que;
    20     que.push(P(x,y));        //第一个结点入栈
    21     flag[x][y]=t;            //代表访问过
    22     
    23     while(!que.empty()){
    24         P cur=que.front();
    25         que.pop();
    26         int tx=cur.first;
    27         int ty=cur.second;
    28         sum++;
    29         
    30         if(mapp[tx][ty]==1){        //则将0进行入队 四个方向搜索 
    31             for(int i=0;i<4;i++){
    32                 int mx=tx+dx[i];
    33                 int my=ty+dy[i];
    34                 if(mapp[mx][my]==0&&flag[mx][my]==0&&mx>=1&&mx<=n&&my>=1&&my<=n){    //没访问过 
    35                     que.push(P(mx,my));
    36                     flag[mx][my]=t;
    37                 }
    38             }
    39         }else if(mapp[tx][ty]==0){
    40             for(int i=0;i<4;i++){
    41                 int mx=tx+dx[i];
    42                 int my=ty+dy[i];
    43                 if(mapp[mx][my]==1&&flag[mx][my]==0&&mx>=1&&mx<=n&&my>=1&&my<=n){    //没访问过 
    44                     que.push(P(mx,my));
    45                     flag[mx][my]=t;
    46                 }
    47             }
    48         }
    49     }
    50     return sum;
    51 }
    52 int main(){
    53     cin>>n>>m;
    54     for(re int i=1;i<=n;i++){
    55         for(re int j=1;j<=n;j++){
    56             char temp;
    57             cin>>temp;
    58             mapp[i][j]=temp-'0';
    59         }
    60     }
    61     
    62     int t=0;                //标记值为1 2 3…… 
    63     for(int i=1;i<=n;i++){            //对迷宫所有点都搜索 
    64         for(int j=1;j<=n;j++){
    65             if(flag[i][j])    continue;        //表示标记过,不需要再进行bfs
    66             t++; 
    67             ans[t]=bfs(i,j,t);        //ans[t]保存标记值为t的连通图的节点数量 
    68         }
    69     }
    70     
    71     for(re int i=1;i<=m;i++){        //卡时间的关键点 
    72         scanf("%d%d",&sx[i],&sy[i]);        //起始坐标     
    73         int x=sx[i],y=sy[i];     
    74         printf("%d
    ",ans[flag[x][y]]);
    75     }
    76     
    77     return 0;
    78 }
  • 相关阅读:
    简易的观察者模式
    SSM项目实战 之 权限管理系统
    SSM项目实战 之 Shiro
    SSM项目实战 之 Maven
    SSM项目实战 之 EasyUI
    Oracle复习思路
    Oracle存储过程 函数 计算使用资源
    Mybatis笔记(二)
    Mybatis笔记(一)
    Oracle表空间 与 分页
  • 原文地址:https://www.cnblogs.com/xwh-blogs/p/12820053.html
Copyright © 2011-2022 走看看