• POJ 3182 The Grove [DP(spfa) 射线法]


    题意:

    给一个地图,给定起点和一块连续图形,走一圈围住这个图形求最小步数


    本来是要做课件上一道$CF$题,先做一个简化版

    只要保证图形有一个点在走出的多边形内就可以了

    $hzc:$动态化静态的思想,假设已经有了路线怎么判断合法

    点在多边形内是“点变多边形不变”,我们反过来维护多边形变

    $f[i][j][0/1]$表示当前走到$(i,j)$,点是否在多边形内

    维护一条向右发出的射线,每次走的时候看看有没有穿过射线就行了

    因为这是个网格,我们可以规定只有从上面经过才算穿过

    然后,这不是$DAG$啊怎么$DP?$

    $spfa$大法好

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const int N=55,M=N*N<<1;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int n,m,g[N][N],sx,sy,a,b;
    int dx[8]={1,-1,0,0,1,-1,1,-1},
        dy[8]={0,0,1,-1,1,-1,-1,1};
    char s[N];
    int d[N][N][2];
    struct Grid{
        int x,y,p;
        Grid(int a=0,int b=0,int c=0):x(a),y(b),p(c){}
    }q[M];
    int head,tail,inq[N][N][2];
    inline void lop(int &x){if(x==M) x=1;}
    inline bool isInter(int x1,int y1,int x2,int y2){
        if(x1<a&&x2==a&&y2>b) return 1;
        if(x2<a&&x1==a&&y1>b) return 1;
        return 0;
    }
    void spfa(){
        d[sx][sy][0]=0;
        head=tail=1;
        q[tail++]=Grid(sx,sy,0);inq[sx][sy][0]=1;
        while(head!=tail){
            Grid u=q[head++];lop(head);
            int x=u.x,y=u.y,p=u.p;//printf("
    now %d %d %d
    ",x,y,p);
            inq[x][y][p]=0;
            for(int i=0;i<8;i++){
                int nx=x+dx[i],ny=y+dy[i];
                if(nx<1||nx>m||ny<1||ny>n||g[nx][ny]) continue;
                int np=p^isInter(x,y,nx,ny);//printf("lok %d %d %d
    ",nx,ny,np);
                if(d[nx][ny][np]>d[x][y][p]+1){//printf("new %d %d %d
    ",nx,ny,np);
                    d[nx][ny][np]=d[x][y][p]+1;
                    if(!inq[nx][ny][np])
                        q[tail++]=Grid(nx,ny,np),lop(tail),inq[nx][ny][np]=1;
                }
            }
        }
        printf("%d
    ",d[sx][sy][1]);
    }
    int main(){
        freopen("in","r",stdin);
        m=read();n=read();
        memset(d,127,sizeof(d));
        for(int i=1;i<=m;i++){
            scanf("%s",s+1);
            for(int j=1;j<=n;j++){
                g[i][j]=(s[j]=='X');
                if(s[j]=='*') sx=i,sy=j;
                else if(s[j]=='X'&&!a) a=i,b=j; 
            }
        }
        //for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) printf("%d%c",g[i][j],j==n?'
    ':' ');
        spfa();
    }
  • 相关阅读:
    第 14 章 结构和其他数据形式(names3)
    第 14 章 结构和其他数据形式(names)
    第 13 章 文件输入/输出 (把文件附加到另一个文件末尾)
    第 13 章 文件输入/输出 (标准I/O)
    第 12 章 存储类别、链接和内存管理(存储类别)
    JS鼠标滚轮判断向上还是向下滚动
    js中一些自带方法和属性
    函数的传入的参数(实参和形参)
    css3实现翻书效果
    redis集群安装
  • 原文地址:https://www.cnblogs.com/candy99/p/6502061.html
Copyright © 2020-2023  润新知