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

Posted Candy?

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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("\nnow %d %d %d\n",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\n",nx,ny,np);
            if(d[nx][ny][np]>d[x][y][p]+1){//printf("new %d %d %d\n",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\n",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?‘\n‘:‘ ‘);
    spfa();
}

 

以上是关于POJ 3182 The Grove [DP(spfa) 射线法]的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 1656 [Usaco2006 Jan] The Grove 树木:bfs射线法

POJ 3666 Making the Grade DP

POJ3267 The Cow Lexicon(DP+删词)

poj 1163 The Triangle(dp)

[poj]1050 To the Max dp

POJ 1426 - Find The Multiple - [DP][BFS]