zoukankan      html  css  js  c++  java
  • 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,&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("
    ");
        }
        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;
    } 
    
    如果自己说什麽都做不到而什麽都不去做的话,那就更是什麽都做不到,什麽都不会改变,什麽都不会结束.
  • 相关阅读:
    Mifare系列3-卡的能源和数据传递(转)
    Mifare系列2-非接触卡标准(转)
    Mifare系列1-简介(转)
    oot 空间不足解决方法
    C语言位操作(转)
    C语言面试题(三)
    C语言运算符和优先级
    C语言面试题(二)
    C语言面试题(一)
    Ubuntu+Win7双系统grub的修复问题
  • 原文地址:https://www.cnblogs.com/Sport-river/p/13934447.html
Copyright © 2011-2022 走看看