HDU 4444 Walk (离散化建图+BFS+记忆化搜索) 绝对经典

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4444


题意:给你一些n个矩形,给你一个起点,一个终点,要你求从起点到终点最少需要转多少个弯


题解:因为矩形数量很少50个,可以离散化成102*102的坐标,但是人可以贴着墙壁走,但不能穿过墙壁

所以每个点要分成9等分。建筑物的边占1/3,但是这样有漏洞。

1、当两个墙壁贴在一起,中间还可以过,所以要填补中间

2、当两个矩形的角重合,中间也可以过,要填补中间,但是只能填补中间一个点,不能填补全部的9个点。

还有一点要注意的是,起点有多个,终点也有多个,从任意一起点到任意一终点即可,因为有一些特殊数据,我的例子里面有


图建好了,直接BFS记忆化搜索即可。


AC代码:

 

#include <iostream>

#include <cstdio>

#include <cstring>

#include <string>

#include <cstdlib>

#include <cmath>

#include <vector>

#include <list>

#include <deque>

#include <queue>

#include <iterator>

#include <stack>

#include <map>

#include <set>

#include <algorithm>

#include <cctype>

#include <sstream>

using namespace std;



typedef long long LL;

const int N=410;

const LL II=100000000;

const int INF=0x3f3f3f3f;

const int M=12345678;

const double PI=acos(-1.0);



int sx,sy,ex,ey;

int si,sj,ei,ej;

int n,nx,ny;

int x[N],y[N];

int g[N][N],step[N][N];

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



struct node

{

    int x1,x2,y1,y2;

}rect[N];



struct xiaohao

{

    int xx,yy;

    int step;

}e,w,xh[M];



int nextint()

{

    int f=1;

    char c;

    while((c=getchar())<'0'||c>'9')

        if(c=='-')

            f=-1;

    int sum=c-'0';

    while((c=getchar())>='0'&&c<='9')

        sum=sum*10+c-'0';

    return sum*f;

}



void lisanhua(int m) //离散化

{

    int i,j;

    sort(x+1,x+m+1);

    sort(y+1,y+m+1);

    nx=1;

    for(i=2;i<=m;i++)//去重

        if(x[i]!=x[i-1])

            x[++nx]=x[i];

    ny=1;

    for(i=2;i<=m;i++)//去重

        if(y[i]!=y[i-1])

            y[++ny]=y[i];

}



int getx(int xx)//数据量大的时候可以用二分查找

{

    for(int i=1;i<=nx;i++)

        if(x[i]==xx)

            return i;

}



int gety(int yy)

{

    for(int i=1;i<=ny;i++)

        if(y[i]==yy)

            return i;

}



void add(int x1,int x2,int y1,int y2)

{

    int i,j;

    for(i=x1;i<=x2;i++)

        for(j=y1;j<=y2;j++)

            g[i][j]=1;//建筑物标记为1

}



void jiantu()

{

    int i,j,x1,x2,y1,y2;

    memset(g,0,sizeof(g));

    si=getx(sx);

    sj=gety(sy);

    ei=getx(ex);

    ej=gety(ey);



    for(i=si*3;i>=si*3-2;i--)//起点,这个地方9个格子全部要标记为5

        for(j=sj*3;j>=sj*3-2;j--)

            g[i][j]=5;

    for(i=ei*3;i>=ei*3-2;i--)//终点,这个地方9个格子全部要标记为6

        for(j=ej*3;j>=ej*3-2;j--)

            g[i][j]=6;



    for(i=1;i<=n;i++)

    {

        x1=getx(rect[i].x1);

        y1=gety(rect[i].y1);

        x2=getx(rect[i].x2);

        y2=gety(rect[i].y2);



        add(x1*3,x2*3-2,y1*3,y2*3-2);

    }

    for(i=1;i<=nx;i++)//将重合的点中间补上

        for(j=1;j<=ny;j++)

        {

            if(g[i*3-2][j*3-2]==1&&g[i*3][j*3]==1||g[i*3-2][j*3]==1&&g[i*3][j*3-2]==1)

                g[i*3-1][j*3-1]=1;

            if(g[i*3-1][j*3-2]==1&&g[i*3-1][j*3]==1)

                g[i*3-1][j*3-1]=1;

            if(g[i*3-2][j*3-1]==1&&g[i*3][j*3-1]==1)

                g[i*3-1][j*3-1]=1;

        }

//    for(i=1;i<=3*nx;i++) //输出离散化后的图

//    {

//        for(j=1;j<=3*ny;j++)

//            printf("%d",g[i][j]);

//        printf("\n");

//    }

}



bool ok(int tx,int ty)

{

    return (tx>=0&&tx<=3*nx&&ty>=0&&ty<=3*ny);

}



void BFS()

{

    int i,j,head=0,tail=0;

    w.step=-1;

    for(i=si*3;i>=si*3-2;i--)

        for(j=sj*3;j>=sj*3-2;j--)

            if(g[i][j]==5)

            {

                w.xx=i;w.yy=j;

                xh[tail++]=w;

            }

    memset(step,INF,sizeof(step));

    step[w.xx][w.yy]=-1;

    while(head!=tail)

    {

        e=xh[head++];

        if(head==M)

            head=0;

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

        {

            w=e;

            w.step++;

            int tx=w.xx+t[i][0];

            int ty=w.yy+t[i][1];

            while(ok(tx,ty)&&g[tx][ty]!=1)//判断是否在界内,而且能走

            {

                if(w.step<step[tx][ty])

                {

                    if(g[tx][ty]==6)

                    {

                        printf("%d\n",w.step);

                        return ;

                    }

                    step[tx][ty]=w.step;

                    w.xx=tx;

                    w.yy=ty;

                    xh[tail++]=w;

                    if(tail==M)

                        tail=0;

                }

                tx+=t[i][0];

                ty+=t[i][1];

            }

        }

    }

    printf("-1\n");

}



int main()

{

    int i,j;

    while(scanf("%d%d%d%d",&sx,&sy,&ex,&ey))

    {

        int x1,x2,y1,y2,m;

        if((!sx)&&(!sy)&&(!ex)&&(!ey))

            break;

        if(sx==ex&&sy==ey)

        {

            printf("0\n");

            continue;

        }

        m=0;

        rect[0].x1=x[++m]=sx;

        rect[0].y1=y[m]=sy;

        rect[0].x2=x[++m]=ex;

        rect[0].y2=y[m]=ey;

        scanf("%d",&n);

        for(i=1;i<=n;i++)

        {

            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);

            if(x1>x2)//防止有的数据先是右上点再是左下点

                swap(x1,x2),swap(y1,y2);



            x[++m]=rect[i].x1=x1;

            y[m]=rect[i].y1=y1;

            x[++m]=rect[i].x2=x2;

            y[m]=rect[i].y2=y2;

        }



        lisanhua(m);

        jiantu();

        BFS();

    }

    return 0;

}



/*

0 0 3 3

4

2 0 4 2

0 2 2 4

4 2 6 4

2 4 4 6



100 -50 10 20

4

-100 15 -20 30

-5 25 50 100

-30 -30 70 -20

70 -20 120 80



5 -1 60 7

3

1 8 101 888

0 0 49 5

50 0 100 6



0 -1 2 1

3

-1 0 0 1

0 1 1 2

1 -2 3 0



0 0 0 10

1

0 5 5 8



0 0 0 10

1

-3 5 0 8



0 0 0 10

2

0 5 5 8

0 2 4 5



0 0 0 10

2

0 5 5 8

-2 1 0 4



0 0 0 10

2

0 0 5 8

-2 1 0 5



0 0 1 10

0



0 -1 2 1

3

-1 0 0 1

0 1 1 2

1 -2 3 0



0 -1 -1 0

9

-3 4 4 5

4 -3 5 5

-2 -3 4 -2

-3 -3 -2 4

-1 2 0 4

1 1 3 3

0 0 1 1

-2 -2 0 0

2 -2 3 0



0 0 0 0





结果应该为:

-1

3

2

1

0

0

0

0

2

1

1

5

*/


 

 

你可能感兴趣的:(HDU)