• 【JZOJ4855】【NOIP2016提高A组集训第6场11.3】荷花池塘


    题目描述

    于大夫建造了一个美丽的池塘,用来让自己愉快的玩耍。这个长方形的池子被分割成了M 行
    和N 列的正方形格子。池塘中有些地方是可以跳上的荷叶,有些地方是不能放置荷叶也不
    能跳上的岩石,其他地方是池水(当然于大夫也是不能游泳的)。于大夫十分有趣,他在池
    塘跳跃的方式和象棋中的马一样可以向八个方向走日字形,而且于大夫只能跳上荷叶。于大
    夫每天从一个给定的有荷叶的地方出发,试图到达另一个给定的有荷叶的地方。但有一天他
    发现自己无论如何也不能到达目的地了,除非再在水中放置几个荷叶。于大夫想让你告诉他,
    最少还需放置几片荷叶?在放置荷叶最少的前提下,最少需要几步能到达目的地?

    数据范围

    10%的数据n,m<=4
    30%的数据n,m<=10
    50%的数据n,m<=30
    70%的数据n,m<=50
    100%的数据n,m<=100

    解法

    SPFA。

    代码

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const char* fin="lilypad.in";
    const char* fout="lilypad.out";
    const int inf=0x7fffffff;
    const int maxn=107,maxtot=10007,maxm=17;
    const int w[8][2]={{2,1},{1,2},{-1,2},{2,-1},{-1,-2},{-2,-1},{-2,1},{1,-2}};
    int n,m,i,j,k,ans,sx,sy,tx,ty;
    int a[maxn][maxn];
    int f[maxn][maxn],g[maxn][maxn];
    int b[maxn*maxn*maxm][2],head,tail;
    bool bz[maxn][maxn];
    void add(int x,int y,int z,int d){
        if (x>0 && x<=n && y>0 && y<=m && a[x][y]!=2){
            if (a[x][y]==0) z++;
            if (z>f[x][y] || z==f[x][y] && d>g[x][y]) return;
            f[x][y]=z;
            g[x][y]=d;
            if (!bz[x][y]){
                b[++tail][0]=x;
                b[tail][1]=y;
                bz[x][y]=true;
            }
        }
    }
    void spfa(){
        int i,j,k,xx,yy,nx,ny;
        head=tail=0;
        add(sx,sy,0,0);
        while (head++<tail){
            xx=b[head][0];
            yy=b[head][1];
            for (i=0;i<8;i++){
                add(xx+w[i][0],yy+w[i][1],f[xx][yy],g[xx][yy]+1);
            }
            bz[xx][yy]=false;
        }
    }
    int main(){
        freopen(fin,"r",stdin);
        freopen(fout,"w",stdout);
        scanf("%d%d",&n,&m);
        for (i=1;i<=n;i++) for (j=1;j<=m;j++){
            scanf("%d",&a[i][j]);
            if (a[i][j]==3) sx=i,sy=j;
            if (a[i][j]==4) tx=i,ty=j;
        }
        memset(f,127,sizeof(f));
        memset(g,127,sizeof(g));
        spfa();
        if (f[tx][ty]<2000000000) printf("%d %d",f[tx][ty],g[tx][ty]);
        else printf("-1 -1");
        return 0;
    }

    启发

    SPFA的关系式只要是二元关系即可。

  • 相关阅读:
    Luogu P1596 [USACO10OCT]湖计数Lake Counting
    Luogu P1757 通天之分组背包
    数据建模笔记1
    单纯形算法 matlab
    有效集 matlab代码
    拟牛顿 DFP matlab
    FR共轭梯度法 matlab
    整数规划
    线性规划 Matlab
    远期、期货和互换(三)
  • 原文地址:https://www.cnblogs.com/hiweibolu/p/6714852.html
Copyright © 2020-2023  润新知