求解解救amaze问题&求解饥饿的小易问题

求解饥饿的小易问题

题目描述

小易总是感觉饥饿,所以作为章鱼的小易经常出去寻找贝壳吃。最开始小易在一个初始位置x_0。对于小易所处的当前位置x,他只能通过神秘的力量移动到 4 * x + 3或者8 * x + 7。因为使用神秘力量要耗费太多体力,所以它只能使用神秘力量最多100,000次。贝壳总生长在能被1,000,000,007整除的位置(比如:位置0,位置1,000,000,007,位置2,000,000,014等)。小易需要你帮忙计算最少需要使用多少次神秘力量就能吃到贝壳。

输入描述:

输入一个初始位置x_0,范围在1到1,000,000,006

输出描述:

输出小易最少需要使用神秘力量的次数,如果使用次数使用完还没找到贝壳,则输出-1

示例1

输入

125000000

输出

1

2、主要思想:

(1)BFS思想,这一点很容易想到。

(2)对于已经访问过的节点,要用一个set进行记录,这样减少非常的多的重复计算,而且未被访问的节点队列queue才不会超级长。 

import java.util.*;
 public class HungriedXiaoYi {
    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);
        long x;
        Set<Long> occur=new HashSet<Long>();
        Queue<Long> queue=new LinkedList<Long>();
        while (scanner.hasNextLong()){
            x=scanner.nextLong();             int front=-1,rear=-1;
            int last=0,level=0;
            queue.add(x%1000000007);
            rear++;
            occur.add(x%1000000007);
            while (level<100001 && !queue.isEmpty()){
                long loc=queue.poll();
                front++;
                if(loc==0){ 
                    System.out.println(level);
                    break;
                }else{
                    if(!occur.contains((4 * loc + 3)%1000000007)) {
                        queue.add((4 * loc + 3) % 1000000007);
                        occur.add((4*loc+3)%1000000007);
                        rear++;
                    }
                    if(!occur.contains((8 * loc + 7)%1000000007)){
                        queue.add((8 * loc + 7)%1000000007);
                        occur.add((8*loc+7)%1000000007);
                        rear++;
                    }
                }
                if(front==last){
                    level++;
                    last=rear;
                }
            }
            if(level==100001 || (level<=100000 && queue.isEmpty()))
                System.out.println(-1);
            queue.clear();
            occur.clear();
        }
    }
}

求解解救amaze问题

问题描述:原始森林中有很多树,如线段树、后缀树和红黑树等,你掌握了所有的树吗?别担心,本问题不会谈论树,而是介绍原始森林中的一些动物,第1种是金刚,金刚是一种危险的动物,如果你遇到金刚,你会死的。第2种是野狗,它不会祥金刚那么危险,但它会咬你。
  Amaze是一个美国的女孩,她不幸迷失于原始森林中。Magicpig非常担心她,他要到原始森林找她。Magicpig知道如果遇到金刚他会死的,野狗也会咬他,而且咬了两次之后他也会死的。Magicpig是多么可怜!
输入的第1行是单个数字t(0<=t<=20),表示测试用例的数目。
  每个测试用例是一个Magicpig地图,之前的一行指出n(0<n<=30),原始森林是一个n*n单元矩阵,其中:
 (1). p表示Magicpig。
 (2). a表示Amaze。
 (3). r表示道路。
 (4). k表示金刚。
 (5). d表示野狗。
  请注意,Magicpig只能在上、下、左、右4个方向移动。
  对于每个测试用例,如果Magicpig能够找到Amaze,则在一行中输出“Yes”,否则在一行中输出“No”。

输入样本:
4
3
pkk
rrd
rda
3
prr
kkk
rra
4
prrr
rrrr
rrrr
arrr
5
prrrr
ddddd
ddddd
rrrrr
rrrra

输出结果:
Yes
No
Yes
No

//代码(DFS):
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
using namespace std;
int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
bool vis[22][22], flag;
char map[22][22];
int n, m, sx, sy;
inline void dfs(int x, int y, int num)
{
    if(flag)
        return;
    for(int i = 0; i < 4; i ++)
    {
        int tx = dir[i][0] + x;
        int ty = dir[i][1] + y;
        if(tx >= 0 && tx < n && ty >= 0 && ty < n && !vis[tx][ty])
        {
            // 如果是金刚,则不能走
            if(map[tx][ty] == 'k')
                continue;

            // 此时被咬第二口,死定了,所以不能走
            if(map[tx][ty] == 'd' && num >= 1)
                continue;
            // 如果是野狗,此时还没有被咬,则可以走,但是要被咬一口
            if(map[tx][ty] == 'd')
            {
                vis[tx][ty] = 1;
                dfs(tx, ty, num + 1);
                if(flag)
                    return;
                vis[tx][ty] = 0;
            }
            if(map[tx][ty] == 'r')
            {
                vis[tx][ty] = 1;
                // 此时的num不需要加
                dfs(tx, ty, num);
                if(flag)
                    return;
                vis[tx][ty] = 0;
            }

            // 找到了
            if(map[tx][ty] == 'a')
            {
                flag = 1;
                return;
            }
        }
    }
}

// 输入端
inline void Input()
{
    // 注意初始化
    memset(map, 0, sizeof(map));
    memset(vis, 0, sizeof(vis));

    scanf("%d", &n);
    for(int i = 0; i < n; i ++)
    {
        scanf("%s", map[i]);
        // 找出起点坐标,记录位置,对起点坐标预处理
        for(int j = 0; j < n; j ++)
            if(map[i][j] == 'p')
            {
                sx = i;
                sy = j;
                // 把起始点变成道路
                map[sx][sy] = 'r';
            }
    }
    
    // 预处理
    flag = 0;
    vis[sx][sy] = 1;
    // 第三个参数记录被狗咬到的次数
    dfs(sx, sy, 0);
}
// 输出端
inline void Output()
{
    if(flag)
        printf("Yes\n");
    else
        printf("No\n");
}
int main()
{
    scanf("%d", &m);
    while(m --)
    {
        Input();

        Output();
    }
    return 0;
}
//代码(BFS):
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
int n, m, sx, sy, ex, ey;
bool vis[22][22], flag;
char map[22][22];
int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
struct data{
	int x;	//x轴坐标
	int y;	//y轴坐标
	int num;	//记录被狗咬的次数
}st, pre;
void BFS()
{
	queue<data> que;
	st.x = sx;
	st.y = sy;
	st.num = 0;
	vis[sx][sy] = 1;
	//起点入队
	que.push(st);
	//不为空的时候进行循环
	while(!que.empty())
	{
		st = que.front();//读取第一个点
		que.pop();	//删除
		//找到终点坐标,输出Yes,终止BFS
		if(st.x == ex && st.y == ey)
		{
			printf("Yes\n");
			flag = 1;
			return;
		}
		//四个方向遍历
		for(int i = 0;i < 4;i ++)
		{
			int tx = st.x + dir[i][0];
			int ty = st.y + dir[i][1];
			
			//如果是金刚的话不可以走
			if(map[tx][ty] == 'k')
				continue;
			
			//如果是狗而且被咬了一次也不可以走,第二次就咬死了
			if(map[tx][ty] == 'd' && st.num == 1)
				continue;

			//已经走过,不可以走
			if(vis[tx][ty] == 1)
				continue;

			//判断是否越界
			if(tx < 0 || tx >= n || ty < 0 || ty >= n)
				continue;
			
			pre.x = tx;
			pre.y = ty;
			vis[tx][ty] = 1;
			
			//判断是否是狗,是的话num累加
			if(map[tx][ty] == 'd')
				pre.num = st.num + 1;
			
			//入队
			que.push(pre);
		}
	}
}

int main()
{
	scanf("%d", &m);
	while(m --)
	{
		memset(map, 0, sizeof(map));
		scanf("%d", &n);
		for(int i = 0;i < n;i ++)
		{
			scanf("%s", map[i]);
			for(int j = 0;j < n;j ++)
				if(map[i][j] == 'p')
				{
					sx = i;
					sy = j;
				}
				else if(map[i][j] == 'd')
				{
					ex = i;
					ey = j;
				}
		}
		flag = 0;
		memset(vis, 0, sizeof(vis));
		BFS();

		if(!flag)
			printf("No\n");
	}
	return 0;
}
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

超翔之逸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值