- 第一题
/*
* 题目描述
* ------------
* | 2 | 1
* |3 | 8
* |-----------
* |4 | 7
* | 5 | 6
* |-----------
* 有一个NxN的矩阵,把里面的(i,j)划分都上述8个区域,米字处(横竖中线、斜线)为0
*
* */
import java.util.Scanner;
public class Main1 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
scanner.close();
int [][] arr = new int[n][n];
double mid = (n-1)/2.0;//中线
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
//23
if (i< mid && j<mid ){
if (i<j) arr[i][j] = 2;
else if (i>j)arr[i][j] = 3;
}
//45
else if (i>mid && j<mid ){
if (n-1-i>j)arr[i][j]=4;
else if (n-1-i<j)arr[i][j]=5;
}
//18
else if (i<mid && j>mid ){
if (n-1-i>j)arr[i][j]=1;
else if (n-1-i<j)arr[i][j]=8;
}
//67
else if (i>mid && j>mid ){
if (i>j)arr[i][j]=6;
else if (i<j)arr[i][j]=7;
}
}
}
for (int i = 0; i <n ; i++) {
for (int j = 0; j <n-1 ; j++) {
System.out.print(arr[i][j]);
System.out.print(" ");
}
System.out.println(arr[i][n-1]);
}
}
}
/*
示例:
input: 10
output:
0 2 2 2 2 1 1 1 1 0
3 0 2 2 2 1 1 1 0 8
3 3 0 2 2 1 1 0 8 8
3 3 3 0 2 1 0 8 8 8
3 3 3 3 0 0 8 8 8 8
4 4 4 4 0 0 7 7 7 7
4 4 4 0 5 6 0 7 7 7
4 4 0 5 5 6 6 0 7 7
4 0 5 5 5 6 6 6 0 7
0 5 5 5 5 6 6 6 6 0
* */
- 第二题
/**
* 题目描述
* 有一个NxM矩阵,矩阵有值只有0和1, 1代表一个人,相邻的人(只包含上下左右相邻)为一组。
* 现在请移动其中一个人,移动后使一个团队的人数尽可能大,求这个最大的值。
* 如:
* 4 4
* 1 0 1 1
* 1 1 0 1
* 0 0 0 0
* 1 1 1 1
*
* 可以把(0,2)移动到(2,0):
* 4 4
* 1 0 0 1
* 1 1 0 1
* 1 0 0 0
* 1 1 1 1
* 形成一个8人的组,是所有移动方案中最大的。
*
* 我的解题思路是:
* 设置一个最大组人数值max,对于每一个0位置,尝试将该位置置1,然后以该位置为入口dfs进入改组,计算人数,更新max,
* dfs遍历的同时会将该组全部置-1。再次dfs把-1还原为1。
* 尝试将所有0变为1后,会得到更新后的max,这个max可能需要-1:
* 如果移动后只有一组,那个这个移动的元素是内部移动,不能从其他组来,所以需要-1
* 判断方式: dfs把最大组置-1,然后访问整个数组,如果还存在1,说明多个组,返回max;否则,返回max-1
*/
public class Main2 {
private int[][] arr;
private int row;
private int col;
public Main2() {
Scanner scanner = new Scanner(System.in);
row = scanner.nextInt();
col = scanner.nextInt();
arr = new int[row][col];
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
arr[i][j] = scanner.nextInt();
}
}
scanner.close();
int max = 0; //最大组人数
int maxi = 0, maxj = 0; //记录最大组的一个元素下标
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (arr[i][j] == 0) {
arr[i][j] = 1; //尝试把0的地方填1
int num = dfs(i, j,arr); //dfs遍历得到该组的人数,同时会将改组全部变为-1
if (num > max) {
max = num; //更新最大值
maxi = i; //更新最大组入口元素下标
maxj = j;
}
recover(i, j,arr); //把该组从-1还原为1
arr[i][j] = 0; //还原该位置的0
}
}
}
dfs(maxi, maxj,arr); //从入口访问最大组,将该组全部置-1
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (arr[i][j]==1){ //还有其他元素是1,表明现在不止一个组,那么那个填充1的0位置,可以是其他组移动过来的
System.out.println(max);
return;
}
}
}
//上面没有返回,说明移动后只有一个组,移动的这个元素也属于本组,于是需要减出来。
System.out.println(max-1);
}
//从[i,j]处进入一个组,统计其人员数,并在访问过程中全部置-1;
int dfs(int i, int j, int[][]arr) {
if (i < 0 || i >= arr.length || j < 0 || j >= arr[0].length || arr[i][j] == 0 || arr[i][j] == -1) return 0;
arr[i][j] = -1;
return 1 +
dfs(i, j + 1,arr) +
dfs(i, j - 1,arr) +
dfs(i - 1, j,arr) +
dfs(i + 1, j,arr);
}
//从[i,j]处进入一个组, 访问全组,将dfs改变的-1还原为1
void recover(int i, int j,int arr[][]) {
if (i < 0 || i >= arr.length || j < 0 || j >= arr[0].length || arr[i][j] !=-1) return;
arr[i][j] = 1;
recover(i, j + 1,arr);
recover(i, j - 1,arr);
recover(i - 1, j,arr);
recover(i + 1, j,arr);
}
public static void main(String[] args) {
Main2 main = new Main2();
}
}
/*
示例:
input:
4 4
1 0 1 1
1 0 1 1
0 1 0 0
1 1 1 1
output:
12
*/
- 第三题
/*
* 题目描述:
* 输入一个数N,大小为M的数组Arr。
* 对于一个数X,如果X能被Arr中的某个数整除,则成X是‘特殊的’
* 对于1~N,判断其中有多少数是‘特殊的’
*
* 可以直接暴力,如下,但是会超时。
* 使用一些优化方法:
* 1. 记录数组中的最大、小值,1~N遍历时 从最小值开始,到最大值时结束。
* 2. 遍历1~N时可以判断是否是素数。
* 3. 不知道还有没有其他优化方法或者更好的解法???
* */
public class Main4 {
private int M;
private int N;
private int[] arr;
public Main4() {
Scanner scanner = new Scanner(System.in);
N = scanner.nextInt();
M = scanner.nextInt();
arr = new int[N];
for (int i = 0; i < M; i++) {
arr[i] = scanner.nextInt();
}
scanner.close();
int res = 0;
for (int i = 1; i <= N; i++) {
for (int a : arr) {
if (i % a == 0) {
res++;
break;
}
}
}
System.out.println(res);
}
}
- 第四题
/*
* 题目描述
* 背包问题:初始背包容量M
* 有N个商品:
* 每个商品:容量(正负,为负表示可以增加背包容量) 、利益(正负)
* 现在选择商品装到背包,使总利益最大
* 这题是01背包问题的改编。
* 01背包问题中商品的体积全部是正,这里可以是负数,表示增大背包空间
* */