gmoj 6841. 【2020.11.5提高组模拟】淘淘蓝蓝之树 林

6841. 【2020.11.5提高组模拟】淘淘蓝蓝之树 林

题目大意

有一个n*m的矩阵,里面有一个密封的图形,矩阵中点与点之间八联通,现给定一个起点,求绕该图形一圈后又回到起点的最短路径

Solution

做法通俗易懂

在封闭图形任意一个点处做一个分割线,spfa求出到分割线下方和绕图形一周后到达分割线上方的最短路

最后在分割线上统计答案

要特别考虑分割线刚好穿到起点的情况,此时要换条线

我的方法是原来先往右边拉线,如果拉到起点上了,就把分割线拉到左边(仅供参考)

#include <cstdio>
#include <cstring>
#include <algorithm>
# define N 2001
#define open(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
using namespace std;
int n,m,i,j,x,y,x1,y1,ans,k,l,r,w,fro,to,f[N*N][2],g[N*N],bz[N][N];
char map[N][N];
const int dir[8][2]={{0,1},{1,0},{-1,0},{0,-1},{1,1},{1,-1},{-1,1},{-1,-1}};
int main()
{
    open("forest");
    scanf("%d%d\n",&n,&m);
    for (i=1;i<=n;i++)
    {
        for (j=1;j<=m;j++)
        {
            scanf("%c",&map[i][j]);
            if (map[i][j]=='*') x=i,y=j;
            if (map[i][j]=='X') x1=i,y1=j;
        }
        scanf("\n");
    }
    if (x1==x && y>y1) fro=0,to=y1;else fro=y1,to=m+1;
    memset(bz,127,sizeof(bz));
    bz[x][y]=0;
    f[1][0]=x;f[1][1]=y; 
    i=0;j=1;
    while (i<j)
    {
        i++;
        x=f[i][0];y=f[i][1];
        if (bz[x][y]<g[i]) continue;
        for (k=0;k<=7;k++)
        {
            if (x+dir[k][0]<=n && x+dir[k][0]>0 && y+dir[k][1]<=m && y+dir[k][1]>0)
            {
                if (g[i]+1>=bz[x+dir[k][0]][y+dir[k][1]] || map[x+dir[k][0]][y+dir[k][1]]=='X') continue;
                if (x+dir[k][0]==x1 && y+dir[k][1]>=fro && y+dir[k][1]<=to) continue; 
                f[++j][0]=x+dir[k][0];
                f[j][1]=y+dir[k][1];
                g[j]=g[i]+1;
                bz[f[j][0]][f[j][1]]=g[j];
            }
        }
    }
    ans=2147483647;
    for (i=fro;i<=to;i++)
    {
        if (!i || i>m) continue;
        for (j=fro;j<=to;j++)
        {
            if (!j || j>m) continue;
        	l=min(i,j);r=max(i,j);
        	w=r-l;
        	if (r-1>=l && r-1>fro) w=r-1-l;
			if (l+1<=r && l+1<to) w=r-l-1; 
			if (l+1<=r-1 && r-1>fro && l+1<to) w=r-l-2;
            ans=min(ans,bz[x1-1][i]+bz[x1+1][j]+w+2);
        }
    }
    printf("%d",ans);
    return 0;
} 
posted @ 2020-11-05 22:42  Sport_River  阅读(257)  评论(0编辑  收藏  举报