zoukankan      html  css  js  c++  java
  • 【洛谷1363】幻象迷宫

    难得的搜索好题

    原题:

    n,m<=1500

    感觉这题有点难度

    逐步想出思路是不会的,只能是灵稽一动,直接发现正解

    bfs+记忆化,每个点记忆的数据为从源点到此处的x和y方向的变化量

    从点a到b转移时,如果b没来过就正常转移,如果来过则进行判断

    如果a的变化量+从a到b的变化量-b的变化量不为(0,0),则此图有解

    如果全图搜索完毕没有发现符合上述条件的点对,则出不去

    为什么呢?

    “a的变化量+从a到b的变化量-b的变化量”本质是把从源点到b的路径反过来,构成一条从源点到a,再到b,再到另一个源点的过程

    如果这条路径的变化量不为零向量,则显然能走到无穷远

    这条路径一定经过源点s,那么是否存在能走到无穷远且不能走到s的路径呢?

    不存在,因为在任意一个点都可以原地折返回到s再回来

    进一步地说,任意两个可到达的点a和b都来自源点,那么在任意一条路径中,拿出两个点,都可以找出一条经过s的衍生路径

    所以保证上面的做法不会漏解

    这道题的关键在于灵活设置记忆化数据,然后发现位移向量的性质,并利用bfs“所有可到达的点都来自源点”的特点

    代码技巧:

    因为存在传送门(即从右边出来可以到左边)的设定,因此此题下标最好从0开始,这样即便于id函数压缩状态,又便于快速处理传送操作

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 int fx[4]={1,-1,0,0},fy[4]={0,0,1,-1};
     5 struct nds{int x,y;}f[1500][1500];
     6 int n,m,a[1500][1500];  char s[1500];
     7 int sx,sy;
     8 int q[3100000],hd=0;
     9 int gtid(int x,int y){  return x*m+y;}
    10 bool bfs(){
    11     q[hd=1]=gtid(sx,sy);
    12     for(int k=1;k<=hd;++k){
    13         int x=q[k]/m,y=q[k]%m;
    14         for(int i=0;i<4;++i){
    15             int tx=(x+fx[i]+n)%n,ty=(y+fy[i]+m)%m;
    16             if(a[tx][ty]){
    17                 if(!f[tx][ty].x && !f[tx][ty].y && (tx!=sx || ty!=sy)){
    18                     f[tx][ty]=(nds){f[x][y].x+fx[i],f[x][y].y+fy[i]};
    19                     q[++hd]=gtid(tx,ty);
    20                 }
    21                 else{
    22                     if(f[x][y].x+fx[i]-f[tx][ty].x!=0)  return true;
    23                     if(f[x][y].y+fy[i]-f[tx][ty].y!=0)  return true;
    24                 }
    25             }
    26         }
    27     }
    28     return false;
    29 }
    30 void prvs(){
    31     for(int i=0;i<n;++i)for(int j=0;j<m;++j)
    32         f[i][j]=(nds){0,0};
    33 }
    34 int main(){
    35     while(scanf("%d%d",&n,&m)!=EOF){
    36         prvs();
    37         for(int i=0;i<n;++i){
    38             scanf("%s",s);
    39             for(int j=0;j<m;++j){
    40                 if(s[j]=='S'){
    41                     sx=i,sy=j;
    42                     s[j]='.';
    43                 }
    44                 a[i][j]=(s[j]=='.' ? 1 : 0);
    45             }
    46         }
    47         printf("%s
    ",(bfs() ? "Yes" : "No"));
    48         /*cout<<sx<<" "<<sy<<endl;
    49         for(int i=0;i<n;++i){
    50             for(int j=0;j<m;++j)
    51                 printf("(%d, %d) ",f[i][j].x,f[i][j].y);
    52             printf("
    ");
    53         }*/
    54     }
    55     return 0;
    56 }
    View Code
  • 相关阅读:
    HDU 1022 Train Problem I
    HDU 1702 ACboy needs your help again!
    HDU 1294 Rooted Trees Problem
    HDU 1027 Ignatius and the Princess II
    HDU 3398 String
    HDU 1709 The Balance
    HDU 2152 Fruit
    HDU 1398 Square Coins
    HDU 3571 N-dimensional Sphere
    HDU 2451 Simple Addition Expression
  • 原文地址:https://www.cnblogs.com/cdcq/p/12263099.html
Copyright © 2011-2022 走看看