Honey Heist

本文介绍了一道编程竞赛题目,主要内容是如何在一个六边形网格中寻找从起点到终点的最短路径,同时避开一些不可通行的点。文章详细解析了问题,并给出了解决方案,包括如何用坐标表示每个点,以及使用广度优先搜索算法进行求解。

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

5092: Honey Heist

时间限制: 1 Sec  内存限制: 128 MB

题目描述

0x67 is a scout ant searching for food and discovers a beehive nearby. As it approaches the honeycomb,0x67 can sense an area inside packed with dried honey that can be easily carried back to the nest and stored for winter. However, it must burrow through the honeycomb to reach the cell containing the sweet loot. If 0x67 can create a passage to the honey to help the other ants find it, it will do so before returning to the nest. The cells of the honeycomb are numbered in row major order, so cell IDs can be assigned as shown below:
When 0x67 discovers the opening to the honeycomb, it enters the cell. Some ants are stronger than others, depending on their age, so 0x67 can only chew through at most N cells before its jaw wears out and must return to the nest to recuperate. The honeycomb is hexagonal, and each edge length is R cells. 0x67 enters through a hole at location A and must get to the honey at location B by chewing a path through no more than N adjacent cells. Because ants can be competitive, 0x67 wants to reach the honey by chewing through the fewest possible cells. 0x67 can also sense some of the cells are hardened with wax and impossible to penetrate, so it will have to chew around those to reach the cell at location B.

Scout ants have rudimentary computational skills, and before 0x67 begins to chew, it will work out where it needs to go, and compute K, the least number of cells it needs to chew through to get from A to B, where B is the Kth cell. If K > N, 0x67 will not be strong enough to make the tunnel. When 0x67 returns to the nest, it will communicate to its nestmates how many cells it chewed through to get to B, or will report that it could not get to the honey.

输入

The input contains two lines. The first line contains five blank separated integers: R N A B X
R: the length (number of cells) of each edge of the grid, where 2 ≤ R ≤ 20. The total number of cells in the grid can be determined by taking a difference of cubes, R3 − (R − 1)3.
N: the maximum number of cells 0x67 can chew through, where 1 ≤ N < R3 − (R − 1)3.
A: the starting cell ID, This cell is located on one of the grid edges: The cell has fewer than six neighbors.
B: the cell ID of the cell containing the honey, where 1 ≤ B ≤ R3 − (R − 1)3.
X: the number of wax-hardened cells, where 0 ≤ X < (R3 − (R − 1)3) − 1.
The second line contains X integers separated by spaces, where each integer is the ID of a wax-hardened cell.
The ID’s, A, B, and all the ID’s on the second line, are distinct positive integers less than or equal to R3 − (R − 1)3.

输出

A single integer K if 0x67 reached the honey at cell B, where B is the Kth cell, otherwise the string No if it was impossible to reach the honey by chewing through N cells or less.

样例输入

6 6 1 45 11
15 16 17 19 26 27 52 53 58 65 74

样例输出

6

来源

mcpc2017 


 

这题的题目意思就是找一个从A到B的最短路,其中有一些点不能走,问最短路径长度是否大于N

这一题的图和一般的搜索的图不太一样,它是一个六边形的图,但是我们仍然可以用坐标x,y来表示每一个点

其中x为第几行,y为这一行的第几个格子

于是这个题目就变成一个简单的广搜了

要注意的一点是在六边形的上半部分和下半部分x,y转移的状态是不一样的

 

#include<cstdio>
#include<iostream>
#include<cstring>
#define N 100000

using namespace std;
int r,n,a,b,x;
int x1,y1,x2,y2;
int check[N]= {0};
int bound[205];  //bound[i]为第i行共有多少个格子

typedef struct
{
    int x,y,step;
} ss;


int pd(int x,int y)   //用来检测x,y点是否合法
{
    if(x<1||x>2*r-1||y<1||y>bound[x])return 0;
    return 1;
}

int f(int x,int y)   // 婷姐推的公式,用来计算第x行的第y个数的序号是多少
{
    if(x<=r)return r*(x-1)+(x-1)*(x-2)/2+y;
    return (3*r-1)*r/2+(5*r-2-x)*(x-1-r)/2+y;
}


int bfs()
{
    if(x1==x2&&y1==y2)return 0;
    ss team[N];
    int c1=0,c2=1;

    team[0].x=x1;
    team[0].y=y1;
    team[0].step=0;
    check[f(x1,y1)]=1;


    while(c1<c2)    //这里就对六边形的上半部分和下半部分做了不同的搜索策略
    {
        ss now=team[c1];
        c1++;

// printf("%d %d %d\n",now.x,now.y,f(now.x,now.y));

        if(now.x<=r&&pd(now.x-1,now.y-1)&&check[f(now.x-1,now.y-1)]==0)
        {
            team[c2].x=now.x-1;
            team[c2].y=now.y-1;
            team[c2].step=now.step+1;
            check[f(team[c2].x,team[c2].y)]=1;
            if(team[c2].x==x2&&team[c2].y==y2)return team[c2].step;
            c2++;
        }



        if(now.x<=r&&pd(now.x-1,now.y)&&check[f(now.x-1,now.y)]==0)
        {
            team[c2].x=now.x-1;
            team[c2].y=now.y;
            team[c2].step=now.step+1;
            check[f(team[c2].x,team[c2].y)]=1;
            if(team[c2].x==x2&&team[c2].y==y2)return team[c2].step;
            c2++;
        }


        if(now.x>r&&pd(now.x-1,now.y+1)&&check[f(now.x-1,now.y+1)]==0)
        {
            team[c2].x=now.x-1;
            team[c2].y=now.y+1;
            team[c2].step=now.step+1;
            check[f(team[c2].x,team[c2].y)]=1;
            if(team[c2].x==x2&&team[c2].y==y2)return team[c2].step;
            c2++;
        }


        if(now.x>r&&pd(now.x-1,now.y)&&check[f(now.x-1,now.y)]==0)
        {
            team[c2].x=now.x-1;
            team[c2].y=now.y;
            team[c2].step=now.step+1;
            check[f(team[c2].x,team[c2].y)]=1;
            if(team[c2].x==x2&&team[c2].y==y2)return team[c2].step;
            c2++;
        }


        if(pd(now.x,now.y-1)&&check[f(now.x,now.y-1)]==0)
        {
            team[c2].x=now.x;
            team[c2].y=now.y-1;
            team[c2].step=now.step+1;
            check[f(team[c2].x,team[c2].y)]=1;
            if(team[c2].x==x2&&team[c2].y==y2)return team[c2].step;
            c2++;
        }


        if(pd(now.x,now.y+1)&&check[f(now.x,now.y+1)]==0)
        {
            team[c2].x=now.x;
            team[c2].y=now.y+1;
            team[c2].step=now.step+1;
            check[f(team[c2].x,team[c2].y)]=1;
            if(team[c2].x==x2&&team[c2].y==y2)return team[c2].step;
            c2++;
        }


        if(now.x<r&&pd(now.x+1,now.y)&&check[f(now.x+1,now.y)]==0)
        {
            team[c2].x=now.x+1;
            team[c2].y=now.y;
            team[c2].step=now.step+1;
            check[f(team[c2].x,team[c2].y)]=1;
            if(team[c2].x==x2&&team[c2].y==y2)return team[c2].step;
            c2++;
        }


        if(now.x<r&&pd(now.x+1,now.y+1)&&check[f(now.x+1,now.y+1)]==0)
        {
            team[c2].x=now.x+1;
            team[c2].y=now.y+1;
            team[c2].step=now.step+1;
            check[f(team[c2].x,team[c2].y)]=1;
            if(team[c2].x==x2&&team[c2].y==y2)return team[c2].step;
            c2++;
        }


        if(now.x>=r&&pd(now.x+1,now.y)&&check[f(now.x+1,now.y)]==0)
        {
            team[c2].x=now.x+1;
            team[c2].y=now.y;
            team[c2].step=now.step+1;
            check[f(team[c2].x,team[c2].y)]=1;
            if(team[c2].x==x2&&team[c2].y==y2)return team[c2].step;
            c2++;
        }


        if(now.x>=r&&pd(now.x+1,now.y-1)&&check[f(now.x+1,now.y-1)]==0)
        {
            team[c2].x=now.x+1;
            team[c2].y=now.y-1;
            team[c2].step=now.step+1;
            check[f(team[c2].x,team[c2].y)]=1;
            if(team[c2].x==x2&&team[c2].y==y2)return team[c2].step;
            c2++;
        }

    }

    return -1;

}



int main()
{

    scanf("%d %d %d %d %d",&r,&n,&a,&b,&x);

    for(int i=0; i<x; i++)
    {
        int aa;
        scanf("%d",&aa);
        check[aa]=1;
    }


    for(int i=1; i<=r; i++)
    {
        bound[i]=i+r-1;
        for(int j=1; j<=i+r-1; j++)
        {
            if(f(i,j)==a)
            {
                x1=i;
                y1=j;
            }
            else if(f(i,j)==b)
            {
                x2=i;
                y2=j;
            }
        }
    }

    for(int i=r+1; i<=2*r-1; i++)
    {
        bound[i]=r+r-2+r+1-i;
        for(int j=1; j<=r+r-2+r+1-i; j++)
        {
            if(f(i,j)==a)
            {
                x1=i;
                y1=j;
            }
            else if(f(i,j)==b)
            {
                x2=i;
                y2=j;
            }
        }
    }

    int ans=bfs();

    if(ans==-1||ans>n)printf("No");
    else
        printf("%d",ans);

    return 0;

}

 

 

转载于:https://www.cnblogs.com/tian-luo/p/8904565.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值