- 第一題
/*
* 題目描述
* ------------
* | 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個商品:
* 每個商品:容量(正負,爲負表示可以增加揹包容量) 、利益(正負)
*
* 現在選擇商品裝到揹包,使總利益最大
* */
明天繼續!