1632: [Usaco2007 Feb]Lilypad Pond

题目链接

题目大意:棋盘,跳马步,格子上有水,莲花,石头,有水的地方可以+莲花,给定起点终点,求+多少莲花才能到达终点,并求在此前提下的步数和方案数

题解:三个要求优先级不同,大力if,只有在优先级高的要求相同时才更新优先级低的

我的收获:多条件最短路

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;

#define pii pair<int,int>
#define mp(x,y) make_pair(x,y)
const int M=35;
#define INF 0x3f3f3f3f
const int dx[]={-2,-1,1,2,2,1,-1,-2};
const int dy[]={-1,-2,-2,-1,1,2,2,1};

int n,m;
int stx,sty,edx,edy;
int mp[M][M],step[M][M],add[M][M];
long long cnt[M][M];
bool vis[M][M];

queue<pii> q;

inline bool out(int x,int y){return x>n||x<1||y>m||y<1;}

void bfs(int x,int y)
{
    memset(add,0x3f,sizeof(add));add[x][y]=0;
    memset(step,0x3f,sizeof(step));step[x][y]=0;
    memset(vis,0,sizeof(vis));vis[x][y]=1;
    memset(cnt,0,sizeof(cnt));cnt[x][y]=1;
    q.push(mp(x,y));
    while(!q.empty())
    {
        pii u=q.front();q.pop();
        int nx=u.first,ny=u.second;vis[nx][ny]=0;
        for(int k=0;k<8;k++){
            int fx=nx+dx[k],fy=ny+dy[k];
            if(out(fx,fy)||mp[fx][fy]==2) continue;
            int len=mp[fx][fy]==0;
            if(add[fx][fy]>add[nx][ny]+len){
                add[fx][fy]=add[nx][ny]+len;
                step[fx][fy]=step[nx][ny]+1;
                cnt[fx][fy]=cnt[nx][ny];
                if(!vis[fx][fy]) vis[fx][fy]=1,q.push(mp(fx,fy)); 
            }
            else if(add[fx][fy]==add[nx][ny]+len){
                if(step[fx][fy]>step[nx][ny]+1)
                {
                    step[fx][fy]=step[nx][ny]+1;
                    cnt[fx][fy]=cnt[nx][ny];
                    if(!vis[fx][fy]) vis[fx][fy]=1,q.push(mp(fx,fy));
                }
                else if(step[fx][fy]==step[nx][ny]+1){
                    cnt[fx][fy]+=cnt[nx][ny];
                    if(!vis[fx][fy]) vis[fx][fy]=1,q.push(mp(fx,fy));
                }
            }
        }
    }
}

void work()
{
    bfs(stx,sty);
    if(add[edx][edy]==INF){puts("-1");return ;}
    printf("%d\n%d\n%lld\n",add[edx][edy],step[edx][edy],cnt[edx][edy]);
}

void init()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            scanf("%d",&mp[i][j]);
            if(mp[i][j]==3) stx=i,sty=j;
            if(mp[i][j]==4) edx=i,edy=j;
        }
}

int main()
{
    init();
    work();
    return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值