[USACO Feb07] 银色莲花池

本文解析了银色莲花池问题的算法实现,通过宽度优先搜索寻找牛贝茜从起点到终点所需的最少莲花数及跳跃步数,并计算可能的路径数目。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[USACO Feb07] 银色莲花池

时间限制:1 s 内存限制:64 MB
译 By CmYkRgB123
描述
Farmer John 建造了一个美丽的池塘,用于让他的牛们审美和锻炼。这个长方形的池子被分割成了 M 行和 N 列( 1 ≤ M ≤ 30 ; 1 ≤ N ≤ 30 ) 正方形格子的 。某些格子上有惊人的坚固的莲花,还有一些岩石,其余的只是美丽,纯净,湛蓝的水。
贝茜正在练习芭蕾舞,她从一个莲花跳跃到另一个莲花,当前位于一个莲花。她希望在莲花上一个一个的跳,目标是另一个给定莲花。她能跳既不入水,也不到一个岩石上。
令门外汉惊讶的是,贝茜的每次的跳跃像国际象棋中的骑士一样:横向移动1,纵向移动2,或纵向移动,横向移动2。贝茜有时可能会有多达8个选择的跳跃。
Farmer John 在观察贝茜的芭蕾舞联系,他意识到有时候贝茜有可能跳不到她想去的目的地,因为路上有些地方没有莲花。于是他想要添加几个莲花使贝茜能够完成任务。一贯节俭的Farmer John想添加最少数量的莲花。当然,莲花不能放在石头上。
请帮助Farmer John确定必须要添加的莲花的最少数量。在添加的莲花最少基础上,算出贝茜从起始点跳到目标点需要的最少的步数。最后,还要算出满足添加的莲花的最少数量时,跳跃最少步数的跳跃路径的条数。
输入
第 1 行: 两个整数 M , N
第 2..M + 1 行:第 i + 1 行,第 i + 1 行 有 N 个整数,表示该位置的状态: 0 为水; 1 为莲花; 2 为岩石; 3 为贝茜开始的位置; 4 为贝茜要去的目标位置.
输出
第 1 行: 一个整数: 需要添加的最少的莲花数. 如果无论如何贝茜也无法跳到,输出 -1.
第 2 行: 一个整数: 在添加的莲花最少基础上,贝茜从起始点跳到目标点需要的最少的步数。如果第1行输出-1,这行不输出。
第 3 行: 一个整数: 添加的莲花的最少数量时,跳跃步数为第2行输出的值的跳跃路径的条数 如果第1行输出-1,这行不输出。
样例输入
4 8
0 0 0 1 0 0 0 0
0 0 0 0 0 2 0 1
0 0 0 0 0 4 0 0
3 0 0 0 0 0 1 0
样例输出
2
6
2

输出说明
至少要添加2朵莲花,放在了’x’的位置。
0 0 0 1 0 0 0 0…0 0 0 1 0 0 0 0
0 x 0 0 0 2 0 1…0 0 0 0 0 2 0 1
0 0 0 0 x 4 0 0…0 0 x 0 x 4 0 0
3 0 0 0 0 0 1 0…3 0 0 0 0 0 1 0
贝茜至少要条6步,有以下两种方案
0 0 0 C 0 0 0 0…0 0 0 C 0 0 0 0
0 B 0 0 0 2 0 F…0 0 0 0 0 2 0 F
0 0 0 0 D G 0 0…0 0 B 0 D G 0 0
A 0 0 0 0 0 E 0…A 0 0 0 0 0 E 0

一道极品搜索题,以后对搜索生疏的时候可以拿来练手QAQ

/*
    Name: 银色莲花池 
    Date: 14/10/16 07:42
    Description: 
        前两问很好解决 一遍宽搜可以很好的解决问题
        但是关键在第三问 要求输出方案(记住这一个教训方案数很可能需要开longlong甚至是写高精度)
        开始时想的是一遍宽搜跑出答案但这显然不现实 因为vis数组会很好的帮你去重
        于是又想到了用一个f[x][y][step][ned]表示在一个点用step步 添加ned荷叶的方案数虽然这可以很好的
        计算所有情况,但是也很好的超过了内存限制,迫不得已看了一下题解 -_-|||
        由于是最短距离到达终点 所以我们可以用 dis[x][y][ned] 表示用ned荷叶到达(x,y) 所用的最短距离
        way[x][y][ned] 表示方案数 于是乎得出了答案 
*/
#include <queue> 
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 35
#define maxm maxn*maxn
#define LL long long
#define inf 0x7f7f7f7f
LL n,m,ans=inf,num=inf,cnt,a[maxn][maxn],startx,starty,endx,endy;
LL st[8][2]={{-2,1},{-1,2},{2,1},{1,2},{-2,-1},{-1,-2},{1,-2},{2,-1}};
struct Node{
    LL x,y,step,ned;
    Node(LL A,LL B,LL C,LL D){
        x=A,y=B,step=C,ned=D;
    }
};
queue<Node> q;
bool vis[maxn][maxn][maxm],Check;
LL dis[maxn][maxn][maxm],way[maxn][maxn][maxm];
void Bfs(){
    while( !q.empty() ){
        Node temp=q.front(); q.pop();
        if(temp.ned>num) continue;
        for(LL i=0;i<8;i++){
            LL xx=temp.x+st[i][0],yy=temp.y+st[i][1];
            if(xx<1||yy<1||xx>n||yy>m)continue;
            if(a[xx][yy]==2)continue;
            if(a[xx][yy]==4){
                Check=1;
                if(num>temp.ned){
                    num=temp.ned;
                    ans=temp.step+1;
                    continue;
                }
                if(num==temp.ned){
                    if(ans>temp.step+1){
                        ans=temp.step+1;
                        continue;
                    }
                }
            }
            if(a[xx][yy]==1 && !vis[xx][yy][temp.ned]){             
                q.push(Node(xx,yy,temp.step+1,temp.ned));
                vis[xx][yy][temp.ned]=1;
            }
            if(a[xx][yy]==0 && !vis[xx][yy][temp.ned+1] ){
                q.push(Node(xx,yy,temp.step+1,temp.ned+1));
                vis[xx][yy][temp.ned+1]=1;
            }
        }
    }
    if(!Check) {printf("-1\n-1\n-1\n"); exit(0);}
    while( !q.empty() )q.pop();
    for(LL i=1;i<=n;i++)for(LL j=1;j<=m;j++)for(LL k=0;k<=num;k++) dis[i][j][k]=inf;
    memset(dis[startx][starty],0,sizeof(dis[startx][starty]));
    memset(way,0,sizeof(way));  way[startx][starty][0]=1;
    q.push(Node(startx,starty,0,0));
    a[endx][endy]=1;
    while( !q.empty() ){
        Node temp=q.front();q.pop();
        for(LL i=0;i<8;i++){
            LL xx=temp.x+st[i][0],yy=temp.y+st[i][1];
            if(xx<1||yy<1||xx>n||yy>m)continue;
            if(a[xx][yy]==2)continue;
            if(a[xx][yy]==1){
                if(temp.step+1<=ans && temp.ned<=num){
                    if(temp.step+1<=dis[xx][yy][temp.ned]){
                        if(temp.step+1<dis[xx][yy][temp.ned]){
                            q.push(Node(xx,yy,temp.step+1,temp.ned));
                            way[xx][yy][temp.ned]=0;
                        }
                        way[xx][yy][temp.ned]+=way[temp.x][temp.y][temp.ned];
                        dis[xx][yy][temp.ned]=temp.step+1;
                    }
                }
            }
            if(a[xx][yy]==0){
                if(temp.ned+1<=num && temp.step+1<=ans){
                    if(temp.step+1<=dis[xx][yy][temp.ned+1]){
                        if(temp.step+1<dis[xx][yy][temp.ned+1]){
                            q.push(Node(xx,yy,temp.step+1,temp.ned+1));
                            way[xx][yy][temp.ned+1]=0;
                        }
                        way[xx][yy][temp.ned+1]+=way[temp.x][temp.y][temp.ned];
                        dis[xx][yy][temp.ned+1]=temp.step+1;        
                    }
                }
            }
        }
    }
}
int main(){
    freopen("silvlily.in","r",stdin); freopen("silvlily.out","w",stdout);
    scanf("%lld%lld",&n,&m);
    LL x,y;
    for(LL i=1;i<=n;i++){
        for(LL j=1;j<=m;j++){
            scanf("%lld",&a[i][j]);
            if(a[i][j]==3){
                q.push(Node(i,j,0,0));
                vis[i][j][0]=1; startx=i;starty=j;
            }
            if(a[i][j]==4){endx=i,endy=j;}
        }
    }
    Bfs();
    printf("%lld\n%lld\n%lld\n",num,ans,way[endx][endy][num]);
    getchar(); getchar();
    return 0;
}
1. 用户与权限管理模块 角色管理: 学生:查看实验室信息、预约设备、提交耗材申请、参与安全考核 教师:管理课题组预约、审批学生耗材申请、查看本课题组使用记录 管理员:设备全生命周期管理、审核预约、耗材采购与分发、安全检查 用户操作: 登录认证:统一身份认证(对接学号 / 工号系统,模拟实现),支持密码重置 信息管理:学生 / 教师维护个人信息(联系方式、所属院系),管理员管理所有用户 权限控制:不同角色仅可见对应功能(如学生不可删除设备信息) 2. 实验室与设备管理模块 实验室信息管理: 基础信息:实验室编号、名称、位置、容纳人数、开放时间、负责人 功能分类:按学科(计算机实验室 / 电子实验室 / 化学实验室)标记,关联可开展实验类型 状态展示:实时显示当前使用人数、设备运行状态(正常 / 故障) 设备管理: 设备档案:名称、型号、规格、购置日期、单价、生产厂家、存放位置、责任人 全生命周期管理: 入库登记:管理员录入新设备信息,生成唯一资产编号 维护记录:记录维修、校准、保养信息(时间、内容、执行人) 报废处理:登记报废原因、时间,更新设备状态为 "已报废" 设备查询:支持按名称、型号、状态多条件检索,显示设备当前可用情况 3. 预约与使用模块 预约管理: 预约规则:学生可预约未来 7 天内的设备 / 实验室,单次最长 4 小时(可设置) 预约流程:选择实验室→选择设备→选择时间段→提交申请(需填写实验目的) 审核机制:普通实验自动通过,高危实验(如化学实验)需教师审核 使用记录: 签到 / 签退:到达实验室后扫码签到,离开时签退,系统自动记录实际使用时长 使用登记:填写实验内容、设备运行情况(正常 / 异常),异常情况需详细描述 违规管理:迟到 15 分钟自动取消预约,多次违规限制预约权限 4. 耗材与安全管理模块 耗材管理: 耗材档案:名称、规格、数量、存放位置、
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值