目录
- 🍋第六题:逆波兰表达式
- 🍊🍊题目描述
- 🍊🍊源代码
- 🍋第七题:核桃的数量
- 🍊🍊题目描述
- 🍊🍊整体思路
- 🍊🍊源代码
- 🍋第八题:打印十字图
- 🍊🍊题目描述
- 🍊🍊整体思路
- 🍊🍊源代码
- 🍋第九题:买不到的数目
- 🍊🍊题目描述
- 🍊🍊思路
- 🍊🍊源代码
- 🍋第十题:剪格子
- 🍊🍊题目描述
- 🍊🍊思路
- 🍊🍊源代码
- 🍊🍊代码解析
- 🍋其他真题
🍋第六题:逆波兰表达式
🍊🍊题目描述
正常的表达式称为中缀表达式,运算符在中间,主要是给人阅读的,机器求解并不方便。
例如:3 + 5 * (2 + 6) - 1
而且,常常需要用括号来改变运算次序。
相反,如果使用逆波兰表达式(前缀表达式)表示,上面的算式则表示为:
- + 3 * 5 + 2 6 1
不再需要括号,机器可以用递归的方法很方便地求解。
为了简便,我们假设:
- 只有 + - * 三种运算符
- 每个运算数都是一个小于10的非负整数
下面的程序对一个逆波兰表示串进行求值。
其返回值为一个数组:其中第一元素表示求值结果,第二个元素表示它已解析的字符数。
static int[] evaluate(String x)
{
if(x.length()==0) return new int[] {0,0};
char c = x.charAt(0);//String的下标也是从0开始的
if(c>='0' && c<='9') return new int[] {c-'0',1};
int[] v1 = evaluate(x.substring(1));//从0开始数,1的话,就包含1了
int[] v2 = __________________________________________; //填空位置
int v = Integer.MAX_VALUE;
if(c=='+') v = v1[0] + v2[0];
if(c=='*') v = v1[0] * v2[0];
if(c=='-') v = v1[0] - v2[0];
return new int[] {v,1+v1[1]+v2[1]};
}
请分析代码逻辑,并推测划线处的代码,通过网页提交。
注意:仅把缺少的代码作为答案,千万不要填写多余的代码、符号或说明文字!!
🍊🍊源代码
答案为:evaluate(x.substring(1+v1[1]))
public class Main {
static int[] evaluate(String x)
{
if(x.length()==0) return new int[] {0,0};
char c = x.charAt(0);
if(c>='0' && c<='9') return new int[] {c-'0',1};
int[] v1 = evaluate(x.substring(1));
int[] v2 = evaluate(x.substring(1+v1[1]));//__________________________________________; //填空位置
int v = Integer.MAX_VALUE;
if(c=='+') v = v1[0] + v2[0];
if(c=='*') v = v1[0] * v2[0];
if(c=='-') v = v1[0] - v2[0];
return new int[] {v,1+v1[1]+v2[1]};
}
public static void main(String[] args) {
// TODO Auto-generated method stub
String a="-+3*5+261";
int []ans=evaluate(a);
System.out.println(ans[0]);
}
}
🍋第七题:核桃的数量
🍊🍊题目描述
小张是软件项目经理,他带领3个开发组。工期紧,今天都在加班呢。为鼓舞士气,小张打算给每个组发一袋核桃(据传言能补脑)。他的要求是:
- 各组的核桃数量必须相同
- 各组内必须能平分核桃(当然是不能打碎的)
- 尽量提供满足1,2条件的最小数量(节约闹革命嘛)
程序从标准输入读入:
a b c
a,b,c都是正整数,表示每个组正在加班的人数,用空格分开(a,b,c<30)
程序输出:
一个正整数,表示每袋核桃的数量。
例如:
用户输入:
2 4 5
程序输出:
20
再例如:
用户输入:
3 1 1
程序输出:
3
资源约定:
峰值内存消耗(含虚拟机) < 64M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.6及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。
🍊🍊整体思路
这是一道代码题。
读完题目,想到的就是暴力。
满足条件的最大值为三数之积。那么从1开始,到三数之积,能被a,b,c整除的就是答案。
🍊🍊源代码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in =new Scanner(System.in);//输入的前提语句
int a=in.nextInt();//输入a
int b=in.nextInt();//输入b
int c=in.nextInt();//输入c
int max=a*b*c;//满足条件的最大值
for(int i=1;i<=max;i++) {//暴力
if(i%a==0&&i%b==0&&i%c==0) {//满足条件的,就是答案
System.out.println(i);//输出答案
break;//找到一个,直接停止程序
}
}
}
}
🍋第八题:打印十字图
🍊🍊题目描述
小明为某机构设计了一个十字型的徽标(并非红十字会啊),如下所示(可参见图片)
对方同时也需要在电脑dos窗口中以字符的形式输出该标志,并能任意控制层数。
为了能准确比对空白的数量,程序要求对行中的空白以句点(.)代替。
输入格式
一个正整数 n (n<30) 表示要求打印图形的层数
输出格式
对应包围层数的该标志。
例如:
用户输入:
1
程序应该输出:
再例如:
用户输入:
3
程序应该输出:
请仔细观察样例,尤其要注意句点的数量和输出位置。
资源约定:
峰值内存消耗 < 64M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include , 不能通过工程设置而省略常用头文件。
提交时,注意选择所期望的编译器类型。
🍊🍊整体思路
读完题目,实际上就是动态规划。跟之前做的打印题没什么两样,声明一个二维字符数组,满足条件的就存$,其余的就存.。之后就for循环打印出来。就是找条件会花费时间。
我们第一次做,是以n=3为例子,先进行最外层的打印。之后找到公式,把死的写成活的即可。下面直接给出答案代码
🍊🍊源代码
import java.util.Scanner;
public class Main {
static int N,R,L;
static char[][] arr;
//存储每一层
static void deal(int n) {
//n=3,总宽为17,最大下标为16
int l,r;
l=(N-n)*2;//每一层的最小下标
r=l+9+4*(n-1)-1;//最大下标
for(int i=l+2;i<=r-2;i++) {//上边界和下边界
arr[l][i]='$';
arr[r][i]='$';
}
//四角四个点
arr[l+1][l+2]='$';
arr[l+1][r-2]='$';
arr[r-1][l+2]='$';
arr[r-1][r-2]='$';
//每角三个点
for(int i=l;i<l+3;i++) {
arr[l+2][i]='$';
arr[r-2][i]='$';
}
for(int i=r;i>r-3;i--) {
arr[l+2][i]='$';
arr[r-2][i]='$';
}
for(int i=l+3;i<=r-3;i++) {
arr[i][l]='$';
arr[i][r]='$';
}
}
static void printAll() {
for(int i=0;i<=R;i++) {
for(int j=0;j<=R;j++) {
if(arr[i][j]!='$') arr[i][j]='.';
System.out.print(arr[i][j]);
}
System.out.println();
}
}
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
N=in.nextInt();
R=9+4*(N-1)-1;//最大下标
arr=new char [R+1][R+1];//声明空间必须是R+1
for(int i=N;i>=1;i--) {
deal(i);
}
int c_i=2*N+2;
int c_j=2*N+2;
arr[c_i][c_j]='$';//二维数组最中间的空间
for(int i=c_i-2;i<c_i+3;i++) {//十字中的横
arr[c_i][i]='$';
}
for(int i=c_i-2;i<c_i+3;i++) {//十字中的竖
arr[i][c_j]='$';
}
printAll();//调用函数输出
}
}
🍋第九题:买不到的数目
🍊🍊题目描述
小明开了一家糖果店。他别出心裁:把水果糖包成4颗一包和7颗一包的两种。糖果不能拆包卖。
小朋友来买糖的时候,他就用这两种包装来组合。当然有些糖果数目是无法组合出来的,比如要买 10 颗糖。
你可以用计算机测试一下,在这种包装情况下,最大不能买到的数量是17。大于17的任何数字都可以用4和7组合出来。
本题的要求就是在已知两个包装的数量时,求最大不能组合出的数字。
输入格式
两个正整数,表示每种包装中糖的颗数(都不多于1000)
要求输出:
一个正整数,表示最大不能买到的糖数
例如:
用户输入:
4 7
程序应该输出:
17
再例如:
用户输入:
3 5
程序应该输出:
7
资源约定:
峰值内存消耗 < 64M
CPU消耗 < 3000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include , 不能通过工程设置而省略常用头文件。
提交时,注意选择所期望的编译器类型。
🍊🍊思路
看完题目,直接遍历就是了。把能买到的数目存起来,再从最大开始往小遍历,买不到的就输出。
这道题还是有公式的,直接输出a*b-a-b
🍊🍊源代码
import java.util.HashSet;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in=new Scanner (System.in);//输入的前提语句
int a=in.nextInt();//输入a
int b=in.nextInt();//输入b
int max=a*b;//最大
HashSet <Integer> set=new HashSet<Integer>();//声明
for(int i=0;a*i<max;i++) {//遍历输出
for(int j=0;a*i+j*b<max;j++) {
set.add(a*i+b*j);//买到的就添加
}
}
for(int i=max-1;i>=0;i--) {
if(!set.contains(i)) {
System.out.println(i);
break;
}
}
}
}
import java.util.HashSet;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in=new Scanner (System.in);//输入的前提语句
int a=in.nextInt();//输入a
int b=in.nextInt();//输入b
System.out.println(a*b-a-b);
}
}
🍋第十题:剪格子
🍊🍊题目描述
如图所示,3 x 3 的格子中填写了一些整数。
我们沿着图中的红色线剪开,得到两个部分,每个部分的数字和都是60。
本题的要求就是请你编程判定:对给定的m x n 的格子中的整数,是否可以分割为两个部分,使得这两个区域的数字和相等。
如果存在多种解答,请输出包含左上角格子的那个区域包含的格子的最小数目。
如果无法分割,则输出 0
程序输入输出格式要求:
程序先读入两个整数 m n 用空格分割 (m,n<10)
表示表格的宽度和高度
接下来是n行,每行m个正整数,用空格分开。每个整数不大于10000
程序输出:在所有解中,包含左上角的分割区可能包含的最小的格子数目。
例如:
用户输入:
3 3
10 1 52
20 30 1
1 2 3
则程序输出:
3
再例如:
用户输入:
4 3
1 1 1 1
1 30 80 2
1 1 1 100
则程序输出:
10
资源约定:
峰值内存消耗 < 64M
CPU消耗 < 5000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include , 不能通过工程设置而省略常用头文件。
提交时,注意选择所期望的编译器类型。
🍊🍊思路
读完题目,我们想到以(0,0)为基点,进行深搜dfs,用递归实现。
在这道题里,每次走动,都有四个方向:上下左右。
最主要的就是这个,其他细节的地方具体看代码解析。
🍊🍊源代码
import java.util.Scanner;
public class Main {
static int[][]g;
static int[][]vis;
private static int n;
private static int m;
private static int total;
private static int ans=Integer.MAX_VALUE;
static void dfs(int i,int j,int steps,int sum) {
if(i<0||i==n||j<0||j==m||vis[i][j]==1) return;
if(sum==total/2) {
ans=Math.min(ans, steps);
return ;
}
if(sum>total/2) return;
vis[i][j]=1;
dfs(i-1,j,steps+1,sum+g[i][j]);
dfs(i+1,j,steps+1,sum+g[i][j]);
dfs(i,j-1,steps+1,sum+g[i][j]);
dfs(i,j+1,steps+1,sum+g[i][j]);
vis[i][j]=0;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in=new Scanner(System.in);
m=in.nextInt();
n=in.nextInt();
g=new int [n][m];
vis=new int [n][m];
for(int i=0;i<n;i++) {
for(int j=0;j<m;j++) {
g[i][j]=in.nextInt();
total+=g[i][j];
}
}
dfs(0,0,0,0);
System.out.println(ans);
}
}
🍊🍊代码解析
4 static int[][]g;
存储输入数组
5 static int[][]vis;
存储访问过的格子
9 private static int ans=Integer.MAX_VALUE;
让ans初始化为一个大数
4~9
这些都是全局变量,在各个函数里面都可以用到
29~30
注意m是列,n才是行
31~32
g=new int [n][m];
vis=new int [n][m];
必须得要初始化才行
32~38
输入存储,并且得到总值total
12 if(i<0||in||j<0||jm||vis[i][j]==1) return;
这是边界条件
12 if(i<0||in||j<0||jm||vis[i][j]==1) return;
边界条件:
下标溢出,以及访问重复
14 ans=Math.min(ans, steps);
取得多个答案较小值
第18行 vis[i][j]=1;
访问过的,进行标记
23 vis[i][j]=0;//走完一个循环,重置
回溯,清零