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();
}
时间: 2024-08-07 08:37:35

POJ 3182 The Grove [DP(spfa) 射线法]的相关文章

poj 1837 Balance (dp,01背包)

链接:poj 1837 题意:有一个天平,天平左右两边各有若干个钩子,总共有C个钩子,有G个钩码, 求将钩码挂到钩子上使天平平衡的方法的总数.其中可以把天枰看做一个以x轴0点作为平衡点的横轴 分析:力臂=重量 *臂长 = g[i]*c[j] 当平衡度k=0时,说明天枰达到平衡,k>0,说明天枰倾向右边(x轴右半轴),k<0则左倾 因此可以定义一个 状态数组dp[i][k],意为在挂满前i个钩码时,平衡度为k的挂法的数量. 由于距离c[i]的范围是-15~15,钩码重量的范围是1~25,钩码数量

POJ 2677 旅行商问题 双调dp或者费用流

Tour Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3408   Accepted: 1513 Description John Doe, a skilled pilot, enjoys traveling. While on vacation, he rents a small plane and starts visiting beautiful places. To save money, John must

LightOj1190 - Sleepwalking(判断点与多边形的位置关系--射线法模板)

题目链接:http://lightoj.com/volume_showproblem.php?problem=1190 题意:给你一个多边形含有n个点:然后又m个查询,每次判断点(x, y)是否在多边形的内部; 射线法判断即可适用于任何(凸或凹)多边形;时间复杂度为O(n); 判断一个点是在多边形内部,边上还是在外部,时间复杂度为O(n):射线法可以正确用于凹多边形: 射线法是使用最广泛的算法,这是由于相比较其他算法而言,它不但可以正确使用在凹多边形上,而且不需要考虑精度误差问题.该算法思想是从

matlab练习程序(射线法判断点与多边形关系)

依然是计算几何. 射线法判断点与多边形关系原理如下: 从待判断点引出一条射线,射线与多边形相交,如果交点为偶数,则点不在多边形内,如果交点为奇数,则点在多边形内. 原理虽是这样,有些细节还是要注意一下,比如射线过多边形顶点或射线与多边形其中一边重合等情况还需特别判断. 这里就不特别判断了,因为我只是熟悉原理,并不是实际运用. 好吧,我实际是太懒了,不想判断了. 结果如下: 结果图和线性分类器的组合有几分相似. matlab代码如下: clear all;close all;clc; polyn=

POJ 3169 Layout (差分约束+SPFA)

Layout Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6832   Accepted: 3292 Description Like everyone else, cows like to stand close to their friends when queuing for feed. FJ has N (2 <= N <= 1,000) cows numbered 1..N standing along a

POJ 1384 Piggy-Bank 背包DP

所谓的完全背包,就是说物品没有限制数量的. 怎么起个这么intimidating(吓人)的名字? 其实和一般01背包没多少区别,不过数量可以无穷大,那么就可以利用一个物品累加到总容量结尾就可以了. 本题要求装满的,故此增加个限制就可以了. #include <stdio.h> #include <stdlib.h> #include <string.h> inline int min(int a, int b) { return a < b? a : b; } c

POJ 3268 Silver Cow Party(SPFA)

Description One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbered 1..N is going to attend the big cow party to be held at farm #X (1 ≤ X ≤ N). A total of M (1 ≤ M ≤ 100,000) unidirectional (one-way roads connects pairs of farms; road i re

POJ 3280 Cheapest Palindrome DP题解

看到Palindrome的题目,首先想到的应该是中心问题,然后从中心出发,思考如何解决. DP问题一般是从更加小的问题转化到更加大的问题,然后是从地往上 bottom up地计算答案的. 能得出状态转移方程就好办了,本题的状态转移方程是: if (cowID[i] == cow{j]) tbl[id][i] = tbl[id][i+1];//相等的时候无需改动 else tbl[id][i] = min(tbl[!id][i+1] + cost[cowID[i]-'a'], tbl[!id][i

poj 1860 Currency Exchange (SPFA、正权回路 bellman-ford)

链接:poj 1860 题意:给定n中货币,以及它们之间的税率,A货币转化为B货币的公式为 B=(V-Cab)*Rab,其中V为A的货币量, 求货币S通过若干此转换,再转换为原本的货币时是否会增加 分析:这个题就是判断是否存在正权回路,可以用bellman-ford算法,不过松弛条件相反 也可以用SPFA算法,判断经过转换后,转换为原本货币的值是否比原值大... bellman-ford    0MS #include<stdio.h> #include<string.h> str