2017年(第八届)蓝桥杯java A组真题(部分)及解决

2017年蓝桥杯java A组真题及解决


其中部分代码借鉴了网络上的其他资源,包括一些其他答主的优秀代码。另一部分代码是本人个人通过思考完成,可能存在一定的漏洞,还请大家包涵。


一、迷宫

【题目概述】
在这里插入图片描述
在这里插入图片描述

【解决思路】
使用两个for循环,对这100个玩家的情况逐一分析。
一开始,假设100个玩家都可以走出迷宫,随后对每个玩家逐一分析,如果发现某一个玩家不能走出迷宫,则将能够走出迷宫的人数减去一。
使用set集合记录玩家走过的路径。添加走过的路径到set集合中,如果添加时add方法的返回值为false,则说明该元素已经存在于set集合中,即玩家曾经从该点经过,现在是第二次经过该点了,从而可以推理出玩家已经走进“死胡同”,即将不停地绕圈。该玩家不能走出迷宫

【个人答案】31

【代码】

public class T1_12_2021 {
	
	char maze[][]=new char[][] {	
		{'U','D','D','L','U','U','L','R','U','L'},
		{'U','U','R','L','L','L','R','R','R','U'},
		{'R','R','U','U','R','L','D','L','R','D'},
		{'R','U','D','D','D','D','U','U','U','U'},
		{'U','R','U','D','L','L','R','R','U','U'},
		{'D','U','R','L','R','L','D','L','R','L'},
		{'U','L','L','U','R','L','L','R','D','U'},
		{'R','D','L','U','L','L','R','D','D','D'},
		{'U','U','D','D','U','D','U','D','L','L'},
		{'U','L','R','D','L','U','U','R','R','R'},
	};
	Set<Integer> path=new HashSet<>();	//记录走过的轨迹
	
	public void compute()
	{
		boolean b=false;
		int outNum=100;
		int m,n;
		for(int i=0;i<10;i++)
		{
			for(int j=0;j<10;j++)
			{
				m=i;
				n=j;
				while((m>=0&&m<=9) && (n>=0&&n<=9))
				{//只要玩家还在迷宫内
					if(maze[m][n]=='U')
					{
 						b=path.add(m*10+n);
						m--;
					}
					else if(maze[m][n]=='D')
					{
						b=path.add(m*10+n);
						m++;
					}
					else if(maze[m][n]=='L')
					{
						b=path.add(m*10+n);
						n--;
					}
					else if(maze[m][n]=='R')
					{
						b=path.add(m*10+n);
						n++;
					}
					if(b==false)
					{//如果b值是false,说明该玩家曾经到达过该点,即将在迷宫里不断死循环
						outNum--;	//能够出迷宫的人减去一
						break;
					}
				}
				//System.out.println(outNum);
				path.clear();
			}
		}
		System.out.println("最终能够出迷宫的人数为:"+outNum);
	}
		
	public static void main(String args[])
	{
		 T1_12_2021 m=new T1_12_2021();
		 m.compute();
		
	}		
}

二、9数算式

【题目概述】
在这里插入图片描述
【解决思路】
这题考察了全排列问题。先使用dfs算法求出1-9的所有排列,再对每一个排列的方法分析乘号的位置。

【个人答案】1341(可能不对。网上还有答案为1625、1340)

【代码】

public class T1_12_2021 {
	
	//全排列问题
	public static int num[]=new int [] {1,2,3,4,5,6,7,8,9};//待排数组
	public static ArrayList<Integer> pathList=new ArrayList<Integer>();//存储每次答案的路径
	public static List<List<Integer>> res=new ArrayList<>();//存储答案
	public static int answer=0;//保存最终结果
	
	public static void dfs()
	{
		if(pathList.size()==num.length)
		{//当所有元素都被加入到pathList中,本次递归终止
			ArrayList<Integer> temp=new ArrayList<Integer>();
			for(int i=0;i<num.length;i++)
			{
				temp.add(pathList.get(i));
			}
			res.add(temp);//把答案加入到答案集合中
			return ;
		}
		for(int i=0;i<num.length;i++)
		{
			if(pathList.contains(num[i])==true)//如果当前元素已经被选择过了,那么跳过
				continue;
			//如果当前元素没有被选择,那么选择当前元素
			pathList.add(num[i]);
			//递归到下一层
			dfs();
			//缩减操作
			pathList.remove(pathList.size()-1);
		}
	}
	
	public static int array2int(int w,int m,int n)
	{
		int ans=0;
		int p=1;
		for(int i=n;i>=m;i--)
		{
			ans=ans+res.get(w).get(i)*p;
			p=p*10;
		}
		return ans;
	}
	
	public static void check(int x1,int x2)
	{//检查计算结果是否是1-9中的每一个数字都出现一次
		int x=x1*x2;
		String s=x+"";//把x转变成string类型
		Set<Character> set=new HashSet<Character>();//使用set集合去重
		for(int i=0;i<s.length() && s.charAt(i)!='0';i++)
		{
			set.add(s.charAt(i));
		}
		if(set.size()==num.length)
		{
			//System.out.println(x1+" * "+x2+" = "+x1*x2);
			answer++;
		}
		
	}
	
	public static void main(String args[])
	{
		 dfs();//对1-9进行全排列,把结果存储在res里面
		 //逐个分析乘号的位置
		 for(int i=0;i<res.size();i++)
		 {
			 for(int j=1;j<num.length;j++)
			 {
				 int x1=array2int(i,0,j);//把array类型的数转化成int类型
				 int x2=array2int(i,j+1,num.length-1);
				 check(x1,x2);//检查计算结果是否是1-9中的每一个数字都出现一次
			 }
		 }
		 answer=answer/2;
		 System.out.println("最终结果是:"+answer);
	}		
}

三、魔方状态

参考这位博主的解决方法:点击链接


四、方格分割

【题目概述】在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
【解决方法】

1.把方块抽象成坐标,左下角的顶点为(0,0)
2.(3,3)为起点,进行深搜。注意对称思想的应用。
3.根据对称性,将深搜得到的结果除以4,得到最终结果。

【答案】509

【代码】

public class T1_12_2021 {
	static int ans=0;
	static int direction[][]=new int[][] {
		{-1,0},
		{1,0},
		{0,-1},
		{0,1}
	};
	static boolean visited[][]=new boolean[7][7];//判断该点是否被访问过
	
	public static void dfs(int x,int y) {
		//如果剪到了方格的边缘,那么停止递归
		if(x<=0 || x>=6 || y<=0 || y>=6) {
			ans++;	//方案数量加一
			return;
		}
		//设置点(x,y)已访问,(x,y)关于(3,3)对称的点也已访问
		visited[x][y]=true;
		visited[6-x][6-y]=true;
		for(int k=0;k<4;k++){//4代表4个方向,形成新坐标(nx,ny)
			int nx=x+direction[k][0];
			int ny=y+direction[k][1];
		//	if(nx<0 || nx>6 || ny<0 ||ny>6)//如果新坐标越界(这个判断条件可以删掉,不影响结果)
		//		continue;
			if(visited[nx][ny]==false) {
				dfs(nx,ny);
			}
		}
		//回溯
		visited[x][y]=false;
		visited[6-x][6-y]=false;
		
	}
	public static void main(String[] args) {
		dfs(3,3);
		System.out.println("最终答案是:"+ans/4);
	
	}
}

五、字母组串

【题目概述】
由 A,B,C 这3个字母就可以组成许多串。
比如:“A”,“AB”,“ABC”,“ABA”,“AACBB” …
现在,小明正在思考一个问题:
如果每个字母的个数有限定,能组成多少个已知长度的串呢?
他请好朋友来帮忙,很快得到了代码,
解决方案超级简单,然而最重要的部分却语焉不详。
请仔细分析源码,填写划线部分缺少的内容。

public class A
{
	// a个A,b个B,c个C 字母,能组成多少个不同的长度为n的串。
	static int f(int a, int b, int c, int n)
	{
		if(a<0 || b<0 || c<0) return 0;
		if(n==0) return 1; 
		
		return ________________________________;  //填空
	}
	
	public static void main(String[] args)
	{
		System.out.println(f(1,1,1,2));
		System.out.println(f(1,2,3,3));
	}
}

【解决方法】递归。这题比较简单
【个人答案】f(a-1,b,c,n-1)+f(a,b-1,c,n-1)+f(a,b,c-1,n-1)


六、最大公共子串

【问题描述】
求两个串的所有子串中能够匹配上的最大长度是多少。
比如:“abcdkkk” 和 “baabcdadabc”,
可以找到的最长的公共子串是"abcd",所以最大公共子串长度为4。
下面的程序是采用矩阵法进行求解的,这对串的规模不大的情况还是比较有效的解法。
请分析该解法的思路,并补全划线部分缺失的代码。

public class Main
{
	static int f(String s1, String s2)
	{
		char[] c1 = s1.toCharArray();
		char[] c2 = s2.toCharArray();
		
		int[][] a = new int[c1.length+1][c2.length+1];
		
		int max = 0;
		for(int i=1; i<a.length; i++){
			for(int j=1; j<a[i].length; j++){
				if(c1[i-1]==c2[j-1]) {
					a[i][j] = __________________;  //填空 
					if(a[i][j] > max) max = a[i][j];
				}
			}
		}
		
		return max;
	}
	
	public static void main(String[] args){
		int n = f("abcdkkk", "baabcdadabc");
		System.out.println(n);
	}
}

【解决思路】考察知识点动态规划。所要填写的东西来源于历史的内容。

【个人答案】a[i-1][j-1]+1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值