<span>蓝桥杯训练1</span>
1.Lake Counting 水洼算法
有一块N×M的土地,雨后积起了水,有水标记为‘W’,干燥为‘.’。八连通的积水被认为是连接在一起的。请求出院子里共有多少水洼?
输入
第一行为N,M(1≤N,M≤110)。
后面输入‘w’与’.’
输出
一行,共有的水洼数。
输入样例('W’表示积水, '.'表示没有积水)
10 12
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
.W.W.....WW.
W.W.W.....W.
.W.W......W.
..W.......W.
输出样例
3
思路:
问题是要我们求解出连着的一片的水洼的数量,对于这类经典的问题,使用其它迭代等的方法是难以求解的,因为我们不知道连着的积水的区域有多少,对于这类问题的求解,我们是采用常用的无死角搜索的深度优先搜索dfs算法来解决,因为dfs能够帮助我们搜索出所有的可能,尝试去走每一条路线,直到所有的路线都被走完了,那么dfs久终止了
基于上面的分析,我们知道要使用dfs来求解,但是我们具体怎么样做呢,这里假如从数组的起始位置开始上往下搜索,那么上一个状从该数组的这个位置的八个方向开始搜索,上一个状态结束之后,那么进入到下一个状态,但是进入到下一个状态的时候它也会往自己的八个方向开始搜索,下一个状态又会搜索至上一个状态的地方,而上一个状态又会往下一个状态搜索,这就造成了递归无法出去了,永远得不到答案而且会导致栈溢出,所以我们该如何避免这种情况呢,其中比较有技巧的方法是当发现这个位置有积水之后把这个位置变为干燥,即将字符’W’变为’.’,这样转移到下一个状态的时候那么往八个方向搜索的时候就不会走之前有积水的地方,因为之前有积水的地方已经干燥了,这样问题就可以解决了,当一个dfs搜索完之后那么它周围的积水都被清除掉了,那么继续寻找下一个有积水的地方然后进行dfs,当所有的积水区域都被赶走之后那么水洼的数量就计算出来了
其中涉及到搜索以自己为中心的八个方向的搜索,所以存在着八个平行状态的搜索,这里使用到了一个技巧就是使用两层的for循环来进行处理
总结一下:比较核心的问题是如何避免在下一个状态进入到上一个状态的时候进入循环的递归,那么这个时候就要将上一次的结果清除掉,这样就不会陷入到无限递归的情况
Java代码
import java.util.Scanner;
public class Lan01 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int m = in.nextInt();//长
int n = in.nextInt();//宽
int count = 0;//计数
char arr[][] = new char[m][n];
for(int i = 0; i < m; i++){
arr[i] = in.next().toCharArray();//调用的next()方法以及toCharArray()方法化为字符数组
}
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){//有'W'的地方说明有积水
if(arr[i][j] == 'W'){
sam(arr, i, j);// 清除一个水洼
count++;
}
}
}
System.out.println(count);//遍历输出
}
private static void sam(char[][] arr, int i, int j) {
arr[i][j] = '.';
for(int k = -1; k <= 1; k++){
for(int p = -1; p <= 1; p++){
if(k == 0 && p == 0) continue;//行的长度: arr.length 列的长度: arr[0].length
if(i + k >=0 && j + p<= arr[0].length - 1 && i + k <= arr.length - 1 && j + p >=0){
if(arr[i + k][j + p] == 'W'){
sam(arr, i + k, j + p);//继续搜寻它的下一个积水
}
}
}
}
}
}
python代码
博主太笨了!写不出来!
C代码
#include<stdio.h>
char field[128][128];
int n,m;
void dfs(int x,int y)
{
int dx,dy,a,b;
field[x][y]='.';
for(dx=-1;dx<=1;dx++)
for(dy=-1;dy<=1;dy++)
{
a=x+dx;
b=y+dy;
if( (a>=0 && a<n) && (b>=0 && b<m) && field[a][b]=='W')
dfs(a,b);
}
}
int main()
{
int i,j,num=0;
while(scanf("%d%d",&n,&m)==2)
{
num=0;
for(i=0;i<n;i++)
scanf("%s",field[i]);
for(i=0;i<n;i++)
for(j=0;j<m;j++)
{
if(field[i][j]=='W')
{
dfs(i,j);
num++;
}
}
printf("%d\n",num);
}
return 0;
}
2.阶乘后的零
给定一个整数 n,返回 n! 结果尾数中零的数量。
示例 1:
输入: 3
输出: 0
解释: 3! = 6, 尾数中没有零。
示例 2:
输入: 5
输出: 1
解释: 5! = 120, 尾数中有 1 个零.
python
class Solution:
def trailingZeroes(self, n: int) -> int:#预期接受一个 int 参数并预期返回一个 int 值:
r = 0
while n >= 5:
n = n // 5
r+=n
return r
java
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
@SuppressWarnings("resource")
Scanner in = new Scanner(System.in);
int num = in.nextInt();
System.out.printf("%d!中的尾数的零有%d个", num, fat(num));
}
private static int fat(int n) {
int count = 0;
while(n>0) {//所有5的倍数会添加一个0,所有5^2的倍数会比5的倍数多添加一个0。
count = count+(n/5);
n=n/5;
}
return count;
}
}
3.猴子分香蕉
5只猴子是好朋友,在海边的椰子树上睡着了。这期间,有商船把一大堆香蕉忘记在沙滩上离去。
第1只猴子醒来,把香蕉均分成5堆,还剩下1个,就吃掉并把自己的一份藏起来继续睡觉。
第2只猴子醒来,重新把香蕉均分成5堆,还剩下2个,就吃掉并把自己的一份藏起来继续睡觉。
第3只猴子醒来,重新把香蕉均分成5堆,还剩下3个,就吃掉并把自己的一份藏起来继续睡觉。
第4只猴子醒来,重新把香蕉均分成5堆,还剩下4个,就吃掉并把自己的一份藏起来继续睡觉。
第5只猴子醒来,重新把香蕉均分成5堆,哈哈,正好不剩!
请计算一开始最少有多少个香蕉。
Java
public class Main {
public static void main(String[] args) {
for (int i = 20; i < 10000; i++) {
double f = (double)i;
for (int j = 1; j <= 4; j++) {
// j是被猴子吃掉的,(f-j)/(double)(5.0)是被猴子藏起来的香蕉
f = f - j - (f - j) / (double)(5.0);
}
if (f % 5 == 0) {
System.out.println(i);
break;
}
}
}
}
python的暴力
xiang=20;
while (True):
if(xiang%5==1):
xiang1=xiang-(xiang-1)/5
xiang1=xiang1-1
if(xiang1%5==2):
xiang2=xiang1-(xiang1-2)/5
xiang2=xiang2-2
if(xiang2%5==3):
xiang3=xiang2-(xiang2-3)/5
xiang3=xiang3-3
if(xiang3%5==4):
xiang4=xiang3-(xiang3-4)/5
xiang4=xiang4-4
if(xiang4%5==0 and xiang4!=0):
print(xiang)
break
xiang=xiang+1
4.哪天返回
小明被不明势力劫持。后被扔到x星站再无问津。小明得知每天都有飞船飞往地球,但需要108元的船票,而他却身无分文。他决定在x星战打工。好心的老板答应包食宿,第1天给他1元钱。
并且,以后的每一天都比前一天多2元钱,直到他有足够的钱买票。
请计算一下,小明在第几天就能凑够108元,返回地球。
Java
public class Main {
public static void main(String[] args) {
int qian=1;//每天的钱
int mon=0;//总钱数
int i=0;//天数
for(i=0;mon<108;i++) {
mon = mon+qian;
qian = qian+2;
}
System.out.println(i);
}
}
python
qian=1
mon=0
i=0
while (mon<108):
mon=mon+qian
qian=qian+2
i=i+1
print(i)
C
#include<stdio.h>
int main()
{
int i;//钱
int d=0;//日子
int sum=0;//总钱数
for(i=0;sum<108;i++){
d++;
sum +=i;
printf("第%d天总%d元\n",d,sum); //本行仅测试用,可删
i=i+2;
}
printf("%d",d);//第多少天成功
return 0;
}