https://www.acmicpc.net/problem/17822
구현 문제
import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main{
static int N, M;
static int[][] disk;
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
int T = Integer.parseInt(st.nextToken());
disk = new int[N+1][M+1];
for(int i=1; i<=N; i++){
st = new StringTokenizer(br.readLine());
for (int j=1; j<=M; j++){
disk[i][j] = Integer.parseInt(st.nextToken());
}
}
for (int i=0; i<T; i++){
st = new StringTokenizer(br.readLine());
int x = Integer.parseInt(st.nextToken());
int d = Integer.parseInt(st.nextToken());
int k = Integer.parseInt(st.nextToken());
rotate(x, d, k);
}
int sum = 0;
for(int i=1; i<=N; i++){
for (int j=1; j<=M; j++){
if (disk[i][j] > 0) sum += disk[i][j];
}
}
System.out.println(sum);
}
/*
x: 번호가 x의 배수에 해당하는 디스크 회전
d: 0 시계방향, 1 반시계방향
k: 회전 칸 수. 1<=k<M
*/
static void rotate(int x, int d, int k){
// 12시 방향부터 시계방향으로 1, 2, ..., M번
int realK = k;
if (d==0) realK *= 1;
else if (d==1) realK *= -1;
for (int i=x; i<=N; i += x){
int[] temp = new int[disk[i].length];
for (int j=1; j<=M; j++){
// 음수 방지를 위해 M를 더하고 나머지연산
temp[(j-1+realK+M)%M + 1] = disk[i][j];
}
disk[i] = Arrays.copyOf(temp, temp.length);
}
processAfterRotation();
// debugPrint();
}
static void processAfterRotation(){
boolean[][] toRemove = new boolean[N+1][M+1];
boolean flag = false;
// 같은 원판 위에서 인접
for (int i=1; i<=N; i++){
if (disk[i][1] == disk[i][M] && disk[i][1] != -1) {
toRemove[i][1] = toRemove[i][M] = true;
}
for (int j=1; j<M; j++){
if (disk[i][j] == -1) continue;
if (disk[i][j] == disk[i][j+1]) toRemove[i][j] = toRemove[i][j+1] = true;
}
}
// 다른 원판 사이에서 인접
for (int j=1; j<=M; j++){
for (int i=1; i<N; i++){
if (disk[i][j] == -1) continue;
if (disk[i][j] == disk[i+1][j]) toRemove[i][j] = toRemove[i+1][j] = true;
}
}
// 제거
for (int i=1; i<=N; i++){
for (int j=1; j<=M; j++){
if (toRemove[i][j]) {
disk[i][j] = -1;
flag = true;
}
}
}
// 해당없음
if (!flag){
int sum = 0;
int count = 0;
for (int i=1; i<=N; i++){
for (int j=1; j<=M; j++){
int val = disk[i][j];
if (val >= 0){
count++;
sum += val;
}
}
}
double mean = count > 0 ? (double) sum / count : 0;
for (int i=1; i<=N; i++){
for (int j=1; j<=M; j++){
if (disk[i][j] < 0) continue;
if (disk[i][j] > mean) disk[i][j] -= 1;
else if (disk[i][j] < mean) disk[i][j] += 1;
}
}
}
}
static void debugPrint(){
StringBuilder sb = new StringBuilder();
for (int i=1; i<=N; i++){
for (int j=1; j<=M; j++){
sb.append(String.format("%4d", disk[i][j]));
}
sb.append("\n");
}
System.out.println(sb.toString());
}
}
양 옆으로 인접한 값을 검사했었으나, N=2이나 M=2 경우에는 양 옆이 존재하지 않기 때문에 이에 대한 처리가 미흡했다.
import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main{
static int N, M;
static int[][] disk;
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
int T = Integer.parseInt(st.nextToken());
disk = new int[N+1][M+1];
for(int i=1; i<=N; i++){
st = new StringTokenizer(br.readLine());
for (int j=1; j<=M; j++){
disk[i][j] = Integer.parseInt(st.nextToken());
}
}
for (int i=0; i<T; i++){
st = new StringTokenizer(br.readLine());
int x = Integer.parseInt(st.nextToken());
int d = Integer.parseInt(st.nextToken());
int k = Integer.parseInt(st.nextToken());
rotate(x, d, k);
}
int sum = 0;
for(int i=1; i<=N; i++){
for (int j=1; j<=M; j++){
if (disk[i][j] > 0) sum += disk[i][j];
}
}
System.out.println(sum);
}
/*
x: 번호가 x의 배수에 해당하는 디스크 회전
d: 0 시계방향, 1 반시계방향
k: 회전 칸 수. 1<=k<M
*/
static void rotate(int x, int d, int k){
// 12시 방향부터 시계방향으로 1, 2, ..., M번
int realK = k;
if (d==0) realK *= 1;
else if (d==1) realK *= -1;
for (int i=x; i<=N; i += x){
int[] temp = new int[disk[i].length];
for (int j=1; j<=M; j++){
// 음수 방지를 위해 M를 더하고 나머지연산
temp[(j-1+realK+M)%M + 1] = disk[i][j];
}
disk[i] = Arrays.copyOf(temp, temp.length);
}
processAfterRotation();
// debugPrint();
}
static void processAfterRotation(){
boolean[][] toRemove = new boolean[N+1][M+1];
boolean flag = false;
// 같은 원판 위에서 인접
for (int i=1; i<=N; i++){
if (disk[i][1] == disk[i][M] && disk[i][1] != -1) {
toRemove[i][1] = toRemove[i][M] = true;
}
for (int j=2; j<M; j++){
if (disk[i][j] == -1) continue;
if (disk[i][j] == disk[i][j-1]) toRemove[i][j] = toRemove[i][j-1] = true;
if (disk[i][j] == disk[i][j+1]) toRemove[i][j] = toRemove[i][j+1] = true;
}
}
// 다른 원판 사이에서 인접
for (int j=1; j<=M; j++){
for (int i=2; i<N; i++){
if (disk[i][j] == -1) continue;
if (disk[i][j] == disk[i-1][j]) toRemove[i][j] = toRemove[i-1][j] = true;
if (disk[i][j] == disk[i+1][j]) toRemove[i][j] = toRemove[i+1][j] = true;
}
}
// 제거
for (int i=1; i<=N; i++){
for (int j=1; j<=M; j++){
if (toRemove[i][j]) {
disk[i][j] = -1;
flag = true;
}
}
}
// 해당없음
if (!flag){
int sum = 0;
int count = 0;
for (int i=1; i<=N; i++){
for (int j=1; j<=M; j++){
int val = disk[i][j];
if (val >= 0){
count++;
sum += val;
}
}
}
double mean = count > 0 ? (double) sum / count : 0;
for (int i=1; i<=N; i++){
for (int j=1; j<=M; j++){
if (disk[i][j] < 0) continue;
if (disk[i][j] > mean) disk[i][j] -= 1;
else if (disk[i][j] < mean) disk[i][j] += 1;
}
}
}
}
static void debugPrint(){
StringBuilder sb = new StringBuilder();
for (int i=1; i<=N; i++){
for (int j=1; j<=M; j++){
sb.append(String.format("%4d", disk[i][j]));
}
sb.append("\n");
}
System.out.println(sb.toString());
}
}
'Study > Coding test' 카테고리의 다른 글
| [JAVA] 백준 17779 - 게리맨더링 2 (0) | 2026.03.25 |
|---|














