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