一、第一题 平方和
1.解题思路
直接模拟
2.知识点
(1)易错点
要给多个案例进行验证,除了题目给的,还要自己去找,尤其是填空题,以防出错
(2) 取模公式:
(a+b)%k=(a%k+b%k)%k
https://www.cnblogs.com/mohari/p/13420064.html
3.代码
public class _A平方和 {
public static void main(String []args) {
long sum=0;
for (int i=1;i<=2019;i++) {
int k=i;
while(k!=0) {
int n=k%10;
if(n==1||n==2||n==0||n==9) {
long g=i*i;//出错点,这个要用原来的数
sum=sum+g;
break;
}
k=k/10;
}
}
System.out.print(sum);
}
}
二、第三题 最大降雨量
1.解题思路
这是考数学题,直接再草稿纸上分析即可
https://blog.youkuaiyun.com/qq_45281807/article/details/108920424
2.补充知识点
(1) 数学问题
以后遇到问题不能直接模拟了,要先思考,草稿纸上面分析题目,好狗蓝桥杯
(2)sort
Arrays.sort也是左闭右开
三、第四题 迷宫
1.解题思路
这题其实可以用深搜和广搜都可以。另外,要注意,因为要字典顺序最小,则要按照DLRU的顺序去搜索,处于前面的且长度最短的路径,就是最小的字典的了。但是!由于这个题的数据集太大了,所以只能用广搜。因为 BFS 得到的解总是最优解,即步数最少的解,那么我们在遍历的时候按照字典序从小到大的顺序进行四个方向遍历进行了。
答案:
(1) 深搜的解题思路
深搜每次进行方向选择时,记录DLRU,然后找到一条路径的时候,就把它存入String数组中,然后回溯,找完所有能够走通的选择路径。然后在将路径数组从小到大排序,数组的第一个元素即为最短的且字典最前的
(2) 广搜的解题思路
由于广搜的特点,当利用广搜找到的第一条路径时,他就是最短的,而且因为我们是利用按照DLRU的顺序去搜,所以字典也是从小到大的,因此广搜的话,找到的第一条路径就是最短路径且字典顺序最小的路径了。
但是广搜要解决的一个问题是,路径怎么去记录?
用两个数组去记录。一个记录下标路径,即到达这一点的前一点的坐标,另外一个数组记录上一点的转向即可
2.广搜代码如下:
注意代码中的易错点和注释
package _10th;
import java.util.*;
//补充知识点1:广搜的迷宫和记录路径如何记录
class Spot{
public int x;
public int y;
Spot(int a,int b){
this.x=a;
this.y=b;
}
}
//其实也可以用深搜的,深搜还比较好记录RULD,然后每次一条路径就把它存到String数组类中
public class _D迷宫 {
private static int dx[]= {1,0,0,-1};
private static int dy[]= {0,-1,1,0};//下左右上
static char [][]way;//记录转左转右
static Spot [][]path;//记录上一个点路径
static char [][]maze;
static boolean[][]marked;
// 用来debug的
// static void print(int n,int m) {
// for(int i=0;i<n;i++) {
// for(int j=0;j<m;j++) {
// System.out.print(way[i][j]+" ");
// }
// System.out.println();
// }
// }
public static void main(String []args) {
Scanner cin=new Scanner (System.in);
int row=cin.nextInt();
int line=cin.nextInt();
cin.nextLine();
maze=new char[row][line];
marked=new boolean[row][line];//初始化
path=new Spot[row][line];
way=new char [row][line];
for(int i=0;i<row;i++) {
String s=cin.nextLine();
maze[i]=s.toCharArray();
}
Deque<Spot> a=new ArrayDeque<>();
Spot start =new Spot(0,0);
a.offer(start);
String s="";
//补充知识点:广搜可以找到迷宫的最短路径,所以找到的第一条路径就是最短路径
//然后为了让字典序最小,所以我们搜索的时候方向顺序为DLRU,下左右上
while(!a.isEmpty()) {
Spot current=a.poll();
if(current.x==row-1&¤t.y==line-1) {
// print(row,line);
int pathx=row-1;int pathy=line-1;
while(pathx!=0||pathy!=0) //注意这个要用或,x,y不同时等于0,否则就到了起点
{
s=s+way[pathx][pathy];
Spot newspot=path[pathx][pathy];
pathx=newspot.x;
pathy=newspot.y;
}
break;
}
marked[current.x][current.y]=true;
for(int i=0;i<4;i++) {
int newx=current.x+dx[i];
int newy=current.y+dy[i];
if(newx>=0&&newx<=row-1&&newy>=0&&newy<=line-1) {
if(maze[newx][newy]=='0'&&marked[newx][newy]==false) {
Spot k=new Spot(newx,newy);
a.offer(k);
//补充知识点:如何记录路径
if(i==0) way[newx][newy]='D';
if(i==1) way[newx][newy]='L';
if(i==2) way[newx][newy]='R';
if(i==3) way[newx][newy]='U';
path[newx][newy]=current;
}
}
}
}
for(int i=s.length()-1;i>=0;i--) {
System.out.print(s.charAt(i));
}
}
}
四、第五题 ERSA解密
1.知识点:如何判断两个数是互质的
五、第七题 外卖店的优先级
1.解题思路
直接模拟。用二维数组存储1-t时刻,各个店铺的优先值
arrayList模拟优先缓存
2.补充知识点
(1)如果需要映射的关系是两个同类型的,用数组列表都行
;若是不同类型的,可以设类或者用MAP
3.代码如下
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int N = s.nextInt();
int M = s.nextInt();
int T = s.nextInt();
Map<Integer, Integer> data = new TreeMap<Integer, Integer>();
//res[i][j] 表示i时刻 j店铺的优先值
int[][] res = new int[T + 1][N + 1];
int[] ids = new int[M];
int[] ts = new int[M];
for (int i = 0; i < M; i++) {
int key = s.nextInt();
int value = s.nextInt();
res[key][value] += 2;
}
int count = 0;
ArrayList<Integer> arrayList=new ArrayList<>();
for (int i = 1; i < T + 1; i++) {
for (int j = 1; j < N + 1; j++) {
if (res[i][j] == 0) {
//当前时刻没有订单,优先值-1,最少为0
res[i][j] = (res[i - 1][j] - 1) > 0 ? (res[i - 1][j] - 1) : 0;
if (res[i][j] <= 3) {
//踢出队列
if(arrayList.contains(j)){
//店铺在队列中则踢出
arrayList.remove((Object)j);
}
}
}
else {
//当前时刻有订单,累加
res[i][j] += res[i - 1][j];
if (res[i][j] > 5) {
//加入队列
if(!arrayList.contains(j)){
arrayList.add(j);
}
}
}
}
}
System.out.println(arrayList.size());
}
六、第九题 糖果
题目
糖果店的老板一共有 M 种口味的糖果出售。为了方便描述,我们将 M 种 口味编号 1 ∼ M。
小明希望能品尝到所有口味的糖果。遗憾的是老板并不单独出售糖果,而 是 K 颗一包整包出售。
幸好糖果包装上注明了其中 K 颗糖果的口味,所以小明可以在买之前就知 道每包内的糖果口味。
给定 N 包糖果,请你计算小明最少买几包,就可以品尝到所有口味的糖 果。
【输入格式】
第一行包含三个整数 N、M 和 K。接下来 N 行每行 K 这整数 T1, T2, · · · , T**K,代表一包糖果的口味。
【输出格式】
一个整数表示答案。如果小明无法品尝所有口味,输出 −1。
【样例输入】
6 5 3
1 1 2
1 2 3
1 1 3
2 3 5
5 4 2
5 1 2
【样例输出】
2
【评测用例规模与约定】
对于30%的评测用例,1 ≤ N ≤ 20。 对于所有评测样例,1≤N≤100,1≤M≤20,1≤K≤20,1≤T**i ≤M。
1.解题思路
(1) 我的思路:
相当于在N包糖果里面从选择1包到选择N包进行全排列,然后进行check,看是否符合条件
但是,由于12和21虽然排列不一样,但是结果是一样的,所以要排除这种重复的数,因此,最优化的思路是采用生成1~N子集即可,不需要生成全排列。
(2) 题解思路:
状态压缩动态规划
https://www.cnblogs.com/smallhester/p/10394328.html
2.补充 知识点
(1)Java如何生成子集合
https://blog.youkuaiyun.com/Warddamn/article/details/115730917
3.代价如下:
//解题思路:相当于在N包糖果里面从选择1包到选择N包进行全排列
//但是12和21虽然排列不一样,但是结果是一样的,所以要排除这种重复的数
//这种思路最多只能过百分之50
//补充知识:Java如何生成子集
import java.util.*;;
public class _I糖果 {
public static int [][]a;
public static boolean flag=false;
public static boolean[]marked;
public static int path[];
public static int K;
public static int M;
public static void main(String []args) {
Scanner cin =new Scanner (System.in);
int N=cin.nextInt();M=cin.nextInt();
K=cin.nextInt();
a=new int [N][K];
path=new int [N];
marked=new boolean[N];
for(int i=0;i<N;i++) {
for(int j=0;j<K;j++) {
a[i][j]=cin.nextInt();
}
}
int i;
for(i=1;i<=N;i++) {
f(0,i,N);
if(flag==true) break;
}
if(flag==false) System.out.print(-1);
else if(flag==true) System.out.print(i);
}
static void f(int index,int number,int total) {
if(index==number) {
if(check(number)) {
flag=true;
}
return;
}
for(int i=0;i<total;i++) {
if(marked[i]==false) {
marked[i]=true;
path[index]=i;
f(index+1,number,total);
marked[i]=false;
}
}
}
static boolean check(int number) {
boolean []candy=new boolean[M+1];
for(int i=0;i<number;i++) {
for(int j=0;j<K;j++) {
candy[a[path[i]][j]]=true;
}
}
for(int k=1;k<=M;k++) {
if(candy[k]==false) return false;
}
return true;
}
}