求解饥饿的小易问题
题目描述
小易总是感觉饥饿,所以作为章鱼的小易经常出去寻找贝壳吃。最开始小易在一个初始位置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输出
12、主要思想:
(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; }