zoukankan      html  css  js  c++  java
  • NOIP2013提高组D2T3 华容道

    n<=30 * m<=30 的地图上,0表示墙壁,1表示可以放箱子的空地。q<=500次询问,每次问:当空地上唯一没有放箱子的空格子在(ex,ey)时,把位于(sx,sy)的箱子移动到(tx,ty)的最小步数。

    第一档:n<=10,m<=10,不加剪枝地乱搞??

    第二档:n<=30,m<=30,q<=10,直接搜索,我觉得这60分够多了。。

    所有档:

    完成移动需要两个过程:空白格移动到指定箱子的周围(不能经过指定箱子),指定箱子在空白格的配合下逐渐逼近目标格子。

    前者可以直接搜索得到,而后者比较麻烦。为了配合指定箱子,空白格必须时刻在指定箱子周围运动,也就是说,他会从指定箱子的上/下/左/右用最小代价移动到箱子的其他方位,然后让箱子朝那个方向前进一格。

    这样的话,实际上是三元状态(x,y,z),(x,y)是当前指定箱子的坐标,z是空格子相对他的方位,这样一些状态之间走来走去,最终走道(tx,ty,上下左右),问最小代价。

    可以发现状态之间走来走去的规则非常简单:一个是(x,y,上)转移成(x-1,y,下)这样的不同格子的相反空格方位的移动,另一种是(x,y,上)转移到(x,y,左)这样的同个格子、空格不同方位的转移。

    同个格子不同方位间转移的代价可以bfs预处理,而,最后查最小代价只需要一次最短路。

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<math.h>
      4 #include<stdlib.h>
      5 #include<algorithm>
      6 #include<queue>
      7 //#include<iostream>
      8 using namespace std;
      9 
     10 //预处理1:play[i][j][0-3][0-3]表示格子(i,j)的上0下1左2右3到上下左右的不经过格(i,j)的最小移动步数
     11 //最短路
     12 
     13 bool isdigit(char c) {return c>='0' && c<='9';}
     14 int qread()
     15 {
     16     char c;int s=0;while (!isdigit(c=getchar()));
     17     do s=s*10+c-'0'; while (isdigit(c=getchar()));return s;
     18 }
     19 
     20 const int inf=0x3f3f3f3f;
     21 int n,m,Q;
     22 int mp[33][33],play[33][33][4][4];
     23 const int dx[]={-1,1,0,0},dy[]={0,0,-1,1};
     24 struct qnode1
     25 {
     26     int x,y,d;
     27 }que1[33*33];int head,tail;bool vis1[33][33];
     28 void pre(int x,int y)
     29 {
     30     mp[x][y]=0;
     31     for (int i=0;i<4;i++)
     32         for (int j=0;j<4;j++)
     33         {
     34             if (i==j) {play[x][y][i][j]=0;continue;}
     35             if (x+dx[i]<1 || x+dx[i]>n || y+dy[j]<1 || y+dy[j]>m ||
     36             !mp[x+dx[i]][y+dy[i]] || !mp[x+dx[j]][y+dy[j]])
     37             {play[x][y][i][j]=inf;continue;}
     38             play[x][y][i][j]=inf;
     39             head=tail=0;
     40             que1[tail].d=0,que1[tail].x=x+dx[i],que1[tail++].y=y+dy[i];
     41             memset(vis1,0,sizeof(vis1));vis1[x+dx[i]][y+dy[i]]=1;
     42             while (head!=tail)
     43             {
     44                 const int nx=que1[head].x,ny=que1[head].y,nd=que1[head].d;head++;
     45                 if (nx==x+dx[j] && ny==y+dy[j])
     46                 {
     47                     play[x][y][i][j]=nd;
     48                     break;
     49                 }
     50                 for (int k=0;k<4;k++)
     51                 {
     52                     int xx=nx+dx[k],yy=ny+dy[k];
     53                     if (xx<1 || xx>n || yy<1 || yy>m || !mp[xx][yy] || vis1[xx][yy]) continue;
     54                     vis1[xx][yy]=1;
     55                     que1[tail].x=xx,que1[tail].y=yy;que1[tail++].d=nd+1;
     56                 }
     57             }
     58         }
     59     mp[x][y]=1;
     60 }
     61 int road(int sx,int sy,int tx,int ty)
     62 {
     63     if (tx==sx && ty==sy) return 0;
     64     head=tail=0;
     65     que1[tail].d=0,que1[tail].x=sx,que1[tail++].y=sy;
     66     memset(vis1,0,sizeof(vis1));vis1[sx][sy]=1;
     67     while (head!=tail)
     68     {
     69         const int nx=que1[head].x,ny=que1[head].y,nd=que1[head].d;head++;
     70         if (nx==tx && ny==ty) return nd;
     71         for (int i=0;i<4;i++)
     72         {
     73             int xx=nx+dx[i],yy=ny+dy[i];
     74             if (xx<1 || xx>n || yy<1 || yy>m || !mp[xx][yy] || vis1[xx][yy]) continue;
     75             vis1[xx][yy]=1;
     76             que1[tail].d=nd+1;que1[tail].x=xx;que1[tail++].y=yy;
     77         }
     78     }
     79     return inf;
     80 }
     81 int dis[33][33][4];bool vis[33][33][4];
     82 struct qnode
     83 {
     84     int x,y,z,d;
     85     bool operator > (const qnode &b) const {return d>b.d;}
     86 };
     87 priority_queue<qnode,vector<qnode>,greater<qnode> > q;
     88 void work()
     89 {
     90     int ex=qread(),ey=qread(),sx=qread(),sy=qread(),tx=qread(),ty=qread();
     91     if (sx==tx && sy==ty)
     92     {
     93         puts("0");
     94         return;
     95     }
     96     for (int i=1;i<=n;i++)
     97         for (int j=1;j<=m;j++)
     98             for (int k=0;k<4;k++)
     99                 dis[i][j][k]=inf;
    100     for (int i=0;i<4;i++)
    101     {
    102         int xx=sx+dx[i],yy=sy+dy[i];
    103         if (xx<1 || xx>n || yy<1 || yy>m || !mp[xx][yy]) continue;
    104         mp[sx][sy]=0;
    105         dis[sx][sy][i]=road(ex,ey,sx+dx[i],sy+dy[i]);
    106         mp[sx][sy]=1;
    107         if (dis[sx][sy][i]<inf) q.push((qnode){sx,sy,i,dis[sx][sy][i]});
    108     }
    109     memset(vis,0,sizeof(vis));
    110     while (!q.empty())
    111     {
    112         const int x=q.top().x,y=q.top().y,z=q.top().z,d=q.top().d;q.pop();
    113         if (vis[x][y][z]) continue;
    114         vis[x][y][z]=1;
    115         if (z==0 && x>1 && mp[x-1][y])
    116             if (dis[x-1][y][1]>d+1)
    117             {
    118                 dis[x-1][y][1]=d+1;
    119                 q.push((qnode){x-1,y,1,d+1});
    120             }
    121         if (z==1 && x<n && mp[x+1][y])
    122             if (dis[x+1][y][0]>d+1)
    123             {
    124                 dis[x+1][y][0]=d+1;
    125                 q.push((qnode){x+1,y,0,d+1});
    126             }
    127         if (z==2 && y>1 && mp[x][y-1])
    128             if (dis[x][y-1][3]>d+1)
    129             {
    130                 dis[x][y-1][3]=d+1;
    131                 q.push((qnode){x,y-1,3,d+1});
    132             }
    133         if (z==3 && y<m && mp[x][y+1])
    134             if (dis[x][y+1][2]>d+1)
    135             {
    136                 dis[x][y+1][2]=d+1;
    137                 q.push((qnode){x,y+1,2,d+1});
    138             }
    139         for (int i=0;i<4;i++) if (i!=z)
    140             if (dis[x][y][i]>d+play[x][y][z][i])
    141             {
    142                 dis[x][y][i]=d+play[x][y][z][i];
    143                 q.push((qnode){x,y,i,d+play[x][y][z][i]});
    144             }
    145     }
    146     int ans=min(dis[tx][ty][0],min(dis[tx][ty][1],min(dis[tx][ty][2],dis[tx][ty][3])));
    147     printf("%d
    ",(ans)>=inf?-1:ans);
    148 }
    149 int main()
    150 {
    151     n=qread(),m=qread(),Q=qread();
    152     for (int i=1;i<=n;i++)
    153         for (int j=1;j<=m;j++)
    154             mp[i][j]=qread();
    155     for (int i=1;i<=n;i++)
    156         for (int j=1;j<=m;j++)
    157             if (mp[i][j])
    158                 pre(i,j);
    159     while (Q--) work();
    160     return 0;
    161 }
    View Code

    然而注意判断答案为0.。。。。。。没判被卡成65分 不如暴力

  • 相关阅读:
    游戏开发中——垂直同步、绘制效率、显示器刷新频率与帧率
    python 异常
    python 多文件知识
    python if,for,while
    python 算术运算
    1.英语单词笔记
    Java import的作用
    java基础点
    Eclipse Java注释模板设置详解
    Java文档注释详解
  • 原文地址:https://www.cnblogs.com/Blue233333/p/7770978.html
Copyright © 2011-2022 走看看