[JAVA] 4013번 : 특이한 자석 (SWEA) & 14891번 : 톱니바퀴 (BOJ)
입출력 형식만 다르고 사실상 같은 문제라서 같이 적어보는 졸린김에 잠깰겸 적는 풀이 히힛
https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AWIeV9sKkcoDFAVH
SW Expert Academy
SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!
swexpertacademy.com
처음에 제출했을 때는 계속 터져버렸다
그리고 이후에 답을 그냥 보고 이해하는 식으로 풀었다.
사실 답 보고 금방 이해했다. 그냥 머릿속에 있는걸 코드로 표현을 못하는게 문제였기 때문이다...
[Java/자바 swea 4013] 특이한 자석
풀이 처음 스택을 쓰려고 했는데 엄청 복잡했습니다... 그래서 2차원 배열을 통해 구현했습니다. map 4x8 2차원 형태로 저장하구 , arr에 시계면 1, 반시계면 -1, 회전 하지않는다면 0 으로 담았습니다
kwangkyun-world.tistory.com
1. solve 함수
방향 배열에 각 상태에 따라 방향을 담는다.
방향을 담아야 해당 방향에 맞게 자석을 돌리기 때문!
그림을 보면 idx 를 1에서 시작한다면 현재 자석은 3, 다음 자석은 7번이랑 비교하게 된다. (idx 를 0에서 시작한다면 현재 자석은 2, 다음 자석은 6이겠죵)
static void solve(int x, int d) {
dArr[x] = d; // 받아온 방향
// 오른쪽으로 회전
for(int i=x+1;i<4;i++) {
if(map[i][6]==map[i-1][2]) {
break;
}
else dArr[i] = -dArr[i-1];
}
// 왼쪽으로 회전
for(int i=x-1;i>=0;i--) {
if(map[i][2]==map[i+1][6]) {
break;
}
else dArr[i] = -dArr[i+1];
}
rotation();
}
처음에 내가 생각했던건 배열을 담아야지 보다는 그냥 변수로 두고 함수로 빼려고 했다.
// 처음 : 화살표 위치
static void solve(int x, int d){
// S극 : 1
// N극 : 0
// 시계 : 1, 반시계 : -1
// idx : 3이랑 7 이랑 물려 있음
// 1. idx 에 물려 있는 값 먼저 확인
// x 랑 x+1
// 2. 값이 다르면 서로 다른 극
// 3. 서로 반대 방향 으로 회전
boolean res[] = new boolean[4];
for(int i=1;i<=3;i++) {
// 다른 지 같은 지 결과 배열에 저장
// 1, 2 (3, 7)
// 2, 3 (3, 7)
// 3, 4 (3, 7)
if(map[i][3]!=map[i+1][7]) {
res[i] = true; // 다르면 true
}else {
res[i] = false; // 같으면 false
}
}
// 나 기준 전, 후 확인
// 다음 꺼랑 비교 할때 -> 내가 3 다음 꺼가 7
// 이전 꺼랑 비교 할때 -> 내가 7 이전 꺼가 3
// 다르면 그때
if(x==1) {
if(res[x]) {
rotation(x, d);
rotation(x+1, -d);
if(res[x+1]) {
rotation(x+2, d);
if(res[x+2]) {
rotation(x+3, -d);
}
}
}
}else if(x==2) {
if(res[x-1]) { // 1
rotation(x-1, -d);
rotation(x, d);
if(res[x]) { // 2
rotation(x+1, -d);
if(res[x+1]) { // 3
rotation(x+2, d);
}
}
}
}else if(x==3) {
if(res[x-1]) {
rotation(x-1, -d);
rotation(x, d);
if(res[x-2]) {
rotation(x-2, d);
}
if(res[x]) {
rotation(x+1, -d);
}
}
}else {
if(res[x-1]) {
rotation(x-1, -d);
rotation(x, d);
if(res[x-2]) {
rotation(x-2, -d);
if(res[x-3]) {
rotation(x-3, d);
}
}
}
}
}
이렇게 아주 비효율적인 만약에 코드를 생각했었다 바보.
2. rotation 함수
// 회전
static void rotation() {
for(int i=0;i<4;i++) {
if(dArr[i]==0) continue;
else if(dArr[i]==1) {
// 시계 방향 회전
int tmp = map[i][7];
for(int y=7;y>=1;y--) {
map[i][y] = map[i][y-1];
}
map[i][0]=tmp;
}else if(dArr[i]==-1){ // -1
// 반시계 방향 회전
int tmp = map[i][0];
for(int y=0;y<=6;y++) {
map[i][y] = map[i][y+1];
}
map[i][7]=tmp;
}
}
}
그리고 회전하는것도 코드를 잘못 작성했었는데, 이전꺼를 다음꺼에 넣거나 다음꺼를 현재꺼에 넣어야하는데, 난 반대로 했었다. 아래처럼....하면 기존 값을 넣는게 아니라 이미 바뀌어진 값을 넣는거라 그냥 값이 이상하게 나온다.
// map 회전
static void rotation(int x, int d) {
// x : 행 번호
// 시계
if(d==1) {
// 1. 마지막 값을 tmp 에 저장
int tmp = map[x][8];
// 2. 한 칸 식 오른쪽
for(int y=1;y<=7;y++) {
map[x][y+1] = map[x][y];
}
// 3. tmp 에 저장한 값 처음에 다시 저장
map[x][1] = tmp;
}else { // 반시계
// 반시계
// 1. 처음 값을 tmp 에 저장
int tmp = map[x][1];
// 2. 한 칸 씩 왼쪽
for(int y=8;y>=2;y--) {
map[x][y-1] = map[x][y];
}
// 3. tmp 에 저장한 값 마지막에 다시 저장
map[x][8] = tmp;
}
쨋든 이 2개의 함수를 이용하면 쉽게 답을 구할수있었다!
그냥 방향 배열에 방향 담고 그 방향에 맞게 배열을 돌려주기만 하면 되는 문제! 전체 코드는 아래와 같다!
import java.io.*;
import java.util.*;
public class Solution {
static int k, map[][], n, dir, dArr[], ans=0;
public static void main(String[] args) throws Exception, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
int T = Integer.parseInt(br.readLine());
for(int tc=1; tc<=T; tc++) {
st = new StringTokenizer(br.readLine());
k = Integer.parseInt(st.nextToken());
map = new int[4][8];
ans = 0;
for(int i=0;i<4;i++) {
st = new StringTokenizer(br.readLine());
for(int j=0;j<8;j++) {
map[i][j] = Integer.parseInt(st.nextToken());
}
}
for(int i=0;i<k;i++) {
dArr = new int[4]; // 방향 배열
st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken());
dir = Integer.parseInt(st.nextToken());
solve(n-1, dir);
}
for(int i=0;i<4;i++) {
if(map[i][0]==1) { // s 극 일때
ans+=Math.pow(2, i);
// System.out.println(i);
}
}
System.out.println("#" + tc + " " + ans);
}
}
static void solve(int x, int d) {
dArr[x] = d; // 받아온 방향
// 오른쪽으로 회전
for(int i=x+1;i<4;i++) {
if(map[i][6]==map[i-1][2]) {
break;
}
else dArr[i] = -dArr[i-1];
}
// 왼쪽으로 회전
for(int i=x-1;i>=0;i--) {
if(map[i][2]==map[i+1][6]) {
break;
}
else dArr[i] = -dArr[i+1];
}
rotation();
}
// 0 1 2 3 4 5 6 7
// 0 0 1 0 0 1 0 0
// 회전
static void rotation() {
for(int i=0;i<4;i++) {
if(dArr[i]==0) continue;
else if(dArr[i]==1) {
// 시계 방향 회전
int tmp = map[i][7];
for(int y=7;y>=1;y--) {
map[i][y] = map[i][y-1];
}
map[i][0]=tmp;
}else if(dArr[i]==-1){ // -1
// 반시계 방향 회전
int tmp = map[i][0];
for(int y=0;y<=6;y++) {
map[i][y] = map[i][y+1];
}
map[i][7]=tmp;
}
}
}
}
참고로 백준 문제는 "톱니바퀴"랑 동일한 문제였고! 입출력 형식만 아래처럼 다르게 하면 바로 정답이 나온다!
https://www.acmicpc.net/problem/14891
음음 무려 4일전이었군...제출이..
이걸 왜 이제 쓰고있는지
개미한테 부지런함을 배우자!
아차차 백준 전체 코드는 아래랑 같다!
import java.io.*;
import java.util.*;
class Main {
static int k, map[][], ans, n, dir, arr[];
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
map = new int[5][9];
// 4개의 자석
for(int i=1;i<=4;i++) {
String line = br.readLine();
// 각 자석은 8개의 '날' 을 가지고 있음
for(int j=0;j<8;j++) {
map[i][j] = line.charAt(j) -'0';
}
}
st = new StringTokenizer(br.readLine());
k = Integer.parseInt(st.nextToken());
// k 번 회전
for(int i=0;i<k;i++) {
arr = new int[5];
st = new StringTokenizer(br.readLine());
n = Integer.parseInt(st.nextToken()); // 몇 번
dir = Integer.parseInt(st.nextToken()); // 방향
solve(n , dir); // 회전 할 때마다
// map 은 공통 으로 활용
}
ans = 0;
// 1 번 -> N극 0점 S극 1점 (2 의 0승)
// 2 번 -> N극 0점 S극 2점 (2 의 1승)
// 3 번 -> N극 0점 S극 4점 (2 의 2승)
// 4 번 -> N극 0점 S극 8점 (2 의 3승)
for(int i=1;i<=4;i++) {
if(map[i][0]==1) { // S극 일 때만 점수
ans+=Math.pow(2, i-1);
}
}
// 임의의 자석 1 칸씩 k 번 회전
// 하나의 자석이 1칸 회전 될 때,
System.out.println(ans);
}
// 처음 : 화살표 위치
// S극 : 1
// N극 : 0
// 시계 : 1, 반시계 : -1
static void solve(int x, int d){
arr[x] = d; // 방향 배열
// idx : 3이랑 7 이랑 물려 있음
// 1. idx 에 물려 있는 값 먼저 확인
// x 랑 x+1
// 2. 값이 다르면 서로 다른 극
// 3. 서로 반대 방향 으로 회전
// 오른쪽
for(int i=x+1;i<=4;i++) {
if(map[i][6]==map[i-1][2]) {
break;
}
else arr[i] = -arr[i-1];
}
// 왼쪽
for(int i=x-1;i>=1;i--) {
if(map[i+1][6]==map[i][2]) {
break;
}
else arr[i] = -arr[i+1];
}
rotation();
}
// map 회전
static void rotation() {
// x : 행 번호
for(int i=1;i<=4;i++) {
if(arr[i]==0) continue;
else if(arr[i]==1) {
// 시계
// 1. 마지막 값을 tmp 에 저장
int tmp = map[i][7];
// 2. 한 칸 식 오른쪽
for(int y=7;y>=1;y--) {
map[i][y] = map[i][y-1];
}
// 3. tmp 에 저장한 값 처음에 다시 저장
map[i][0] = tmp;
}else if(arr[i]==-1) {
// 반시계
// 1. 처음 값을 tmp 에 저장
int tmp = map[i][0];
// 2. 한 칸 씩 왼쪽
for(int y=0;y<=6;y++) {
map[i][y] = map[i][y+1];
}
// 3. tmp 에 저장한 값 마지막에 다시 저장
map[i][7] = tmp;
}
}
}
}