目录
题目
4795. 安全区域 - AcWing题库https://www.acwing.com/problem/content/4798/
代码一
import java.util.Scanner;
public class Main {
public static long SIZE;
public static void main(String[] args){
//获取数据
Scanner input = new Scanner(System.in);
int size = input.nextInt();
SIZE = size;
int cars = input.nextInt();
int[][] carPlace = new int[cars][2];//默认值为false
for(int i = 0; i < cars; i++){
carPlace[i][0] = input.nextInt();
carPlace[i][1] = input.nextInt();
}
boolean[][] live = new boolean[size][size];
int[] ans = new int[cars];
for(int i = 0; i < cars; i++){
live = putCar(carPlace[i][0], carPlace[i][1], live);
ans[i] = calculateLive(live);
}
//输出
for(int i = 0; i < cars; i++){
System.out.print(ans[i] + " ");
}
}
public static boolean[][] putCar(int x,int y,boolean[][] live){
for(int i = 0; i < SIZE; i++){
for(int j = 0; j < SIZE; j++){
if (i + 1 == x || j + 1 == y){
live[i][j] = true;
}
}
}
return live;
}
public static int calculateLive(boolean[][] live){
int count = 0;
for(int i = 0; i < SIZE; i++){
for(int j = 0; j < SIZE; j++){
if(live[i][j] == false){
count++;
}
}
}
return count;
}
}
思路一
一开始的思路与N皇后有点像,就是利用一个二维boolean棋盘记录某些行和某些列已经被攻击到了。然后遍历这个二维数组,把未被攻击的位置数出来,然后返回。这种方法只能通过一些数比较小的案例,遇到大的数据就会报超时。因为这份代码不能AC就不展开了。
代码二
import java.util.Scanner;
public class Main {
public static void main(String[] args){
//获取数据
Scanner input = new Scanner(System.in);
long size = input.nextInt();
int cars = input.nextInt();
boolean[] line = new boolean[100010];
boolean[] column = new boolean[100010];
int l = 0;
int c = 0;
for(int i = 0; i < cars; i++){
int x = input.nextInt();
if (!line[x]){
line[x] = true;
l++;
}
int y = input.nextInt();
if (!column[y]){
column[y] = true;
c++;
}
long ans = (size - l) * (size - c);
System.out.print(ans + " ");
}
}
}
AC结果
思路二:
其实大概思路也差不多,同样用boolean数组记录行和列“是否被攻击”。只不过从一个二维数组变为两个Boolean数组,大小为100010(题目规定数据:车的数量最多为100000)。然后每放一个车进去,“未被攻击”的区域可以直接用棋盘大小减去行或列已被攻击的数量直接计算出来。
一、获取数据(部分)
//获取数据
Scanner input = new Scanner(System.in);
long size = input.nextInt();
int cars = input.nextInt();
boolean[] line = new boolean[100010];
boolean[] column = new boolean[100010];
int l = 0;
int c = 0;
size表示棋盘的大小,cars表示车的数量。line表示每一行“是否被攻击”,column表示每一列“是否被攻击”,l表示已被攻击的行数,c表示已被攻击的列数。
二、计算
for(int i = 0; i < cars; i++){
int x = input.nextInt();
if (!line[x]){
line[x] = true;
l++;
}
int y = input.nextInt();
if (!column[y]){
column[y] = true;
c++;
}
long ans = (size - l) * (size - c);
System.out.print(ans + " ");
}
分别获取每一个车的坐标到x,y。然后比对各自的Boolean数组(line和column)判断这一行/列是否已经被攻击。若已被攻击则不需要处理,若未被攻击,则将该行/列的状态改为已被攻击(true),并且对应的l或者c数值自增。然后通过(size - l) * (size - c)计算未被攻击区域的大小。输出即可。