1. 화살이 부딫힌 오브젝트가 합당하면 (플랫폼/적) 실행된다

2. SetParent로 인한 scale 변경을 방지하기 위해 임시 부모를 생성한다

3. 임시 부모를 목표 부모(충돌체)에 자식으로 넣는다

4. stickArrow를 생성한다 (사용할 화살과 동일해 보이지만, script와 rigidBody나 collider가 제거된 오브젝트)

5. stickArrow를 임시 부모의 자식으로 넣는다

6. 2초 후 제거한다

(충돌 당시 방향으로 조금 이동시킨 후 작업하면 화살촉이 진짜로 박혀있는 듯 보일듯함)

private void OnCollisionEnter2D(Collision2D other)
{
    GameObject otherObject = other.gameObject;

    if (isArrow && (otherObject.CompareTag("Platform") || otherObject.CompareTag("Enemy")))
    {
        // scale 변경 방지용 쿠션 parent
        GameObject sharedParent = new GameObject("Father");
        sharedParent.transform.position = otherObject.transform.position;
        sharedParent.transform.rotation = otherObject.transform.rotation;
        sharedParent.transform.SetParent(otherObject.gameObject.transform);

        // 고정될 화살 생성
        GameObject newArrow = Instantiate(stickArrow, transform.position, transform.rotation);
        newArrow.transform.SetParent(sharedParent.transform, true);
        //2초 후 소멸
        Destroy(newArrow, 2);
    }
}

 

 

 

벽에 충돌해도 2초간 잘 남아있다

적에게 충돌하면, 2초간 적이 이동해도 따라 이동하며 남아있다 

[문제링크]

 

23288번: 주사위 굴리기 2

크기가 N×M인 지도가 존재한다. 지도의 오른쪽은 동쪽, 위쪽은 북쪽이다. 지도의 좌표는 (r, c)로 나타내며, r는 북쪽으로부터 떨어진 칸의 개수, c는 서쪽으로부터 떨어진 칸의 개수이다. 가장 왼

www.acmicpc.net

 

0. 구현 / 그래프 탐색 문제

 

1. 각 지점의 값 * 같은 값으로 연결된 지점의 수 = 해당 지점의 점수 이므로, 사전에 DFS를 진행해 scoreMap을 제작한다

 

2. dice의 방향은 동-남-서-북 순서로 정의, 2칸 차이나면 반대 방향이고, +1로 진행시 시계방향, -1로 진행시 반시계방향

 

3. 문제 정의대로 dice를 움직인다

  • 이동 가능 판단, 불가시 방향 반대로 전환
  • 해당 방향으로 1칸 이동 (roll 함수 이용), 점수 누적
  • map의 값과 dice값 비교를 통해 방향 전

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

public class Main{
	static int[] dice;
	static int[][] dir = {
			{0,1},{1,0},{0,-1},{-1,0}//시계방향 동남서북
	};
	static int[][]scoreMap;
	static int[][]map;
	
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		dice = new int[] {1, 3, 6, 4, 2, 5};//앞 오 바닥 왼 위 아래
		int x=0,y=0;//init pos 0,0
		int curDir=0;//east
		
		
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");
		int n = pint(st.nextToken());
		int m = pint(st.nextToken());
		int k = pint(st.nextToken());
		
		map = new int[n][m];
		scoreMap = new int[n][m];
		List<Integer> list = new ArrayList<>();
		
		for (int i = 0; i < n; i++) {
			st = new StringTokenizer(br.readLine(), " ");
			for (int j = 0; j < m; j++) {
				map[i][j]=pint(st.nextToken());
			}
		}
		
		//1. scoremap에 연속된 갯수 구하기
		int cnt=1;
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				if(scoreMap[i][j]==0) {
					int curV=dfs(i,j,cnt++);
					list.add(curV);
				}
			}
		}
		//2. map의 값으로 곱, 최종 칸 당 점수 구하기
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				scoreMap[i][j] = list.get(scoreMap[i][j]-1);
				scoreMap[i][j] *=map[i][j];
			}
		}
		
		//3. 주사위 go
		int scoreSum=0;
		for (int i = 0; i < k; i++) {
			//한칸 굴러간다
			int nextX = x+dir[curDir][0];
			int nextY = y+dir[curDir][1];
			//못가면 반대로 굴러간다
			if(nextX<0 || nextX>=n || nextY<0 || nextY>=m) {
				curDir = (curDir+2)%4;
				nextX = x+dir[curDir][0];
				nextY = y+dir[curDir][1];
			}
			x=nextX;y=nextY;
			//해당 방향으로 구르기
			roll(curDir);
			
			//점수먹기
			scoreSum += scoreMap[x][y];
			//방향바꾸기
			//바닥면 = dice[2]
			if(map[x][y]<dice[2]) {
				//밑면이 더 크면 시계방향
				curDir= (curDir+1)%4;
			}
			else if(map[x][y]>dice[2]) {
				//밑면이 더 작으면 반시계방향
				curDir= (curDir+4-1)%4;
			}
			else {
				//do nothing
			}
		}
		System.out.println(scoreSum);
	}
	static void roll(int curDir) {
		int tmp;
		//앞 오 바닥 왼 위 아래
		//east
		if(curDir==0) {
			roll(2);
			roll(2);
			roll(2);
		}
		//south
		else if(curDir==1) {
			tmp = dice[0];
			dice[0]=dice[4];
			dice[4]=dice[2];
			dice[2]=dice[5];
			dice[5]=tmp;
		}
		//west
		else if(curDir==2) {
			tmp = dice[0];
			dice[0]=dice[1];
			dice[1]=dice[2];
			dice[2]=dice[3];
			dice[3]=tmp;
		}
		//north
		else if(curDir==3) {
			roll(1);
			roll(1);
			roll(1);
		}
		
	}
	static int dfs(int x, int y, int cur) {
		int num=1;
		scoreMap[x][y]=cur;
		
		if(x-1>=0 && map[x-1][y]==map[x][y] && scoreMap[x-1][y]==0) {
			num+=dfs(x-1,y,cur);
		}
		if(x+1<map.length && map[x+1][y]==map[x][y] && scoreMap[x+1][y]==0) {
			num+=dfs(x+1,y,cur);
		}
		if(y-1>=0 && map[x][y-1]==map[x][y] && scoreMap[x][y-1]==0) {
			num+=dfs(x,y-1,cur);
		}
		if(y+1<map[0].length && map[x][y+1]==map[x][y] && scoreMap[x][y+1]==0) {
			num+=dfs(x,y+1,cur);
		}
		
		return num;
	}
	
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과 화면

[문제링크]

 

19236번: 청소년 상어

첫째 줄부터 4개의 줄에 각 칸의 들어있는 물고기의 정보가 1번 행부터 순서대로 주어진다. 물고기의 정보는 두 정수 ai, bi로 이루어져 있고, ai는 물고기의 번호, bi는 방향을 의미한다. 방향 bi는

www.acmicpc.net

 

0. 백트래킹 / 구현 문제

 

1. 백트래킹을 위하여, 상어의 각 이동 단계마다 map과 물고기 방향 정보를 저장한다

 

2. 해당 상황에서 물고기 이동 - 가능한 모든 상어 이동에 대해 재귀를 돌린 다음, 저장해둔 정보를 복원하고 이전 단계로 돌아간다

 

3. 각 재귀 단계에서 먹은 물고기 번호의 합을 저장, 더이상 진행 불가능할때 전역변수인 maxEat과 비교, 갱신한다

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main{
	static int[][] dir = {
			{-1,0},{-1,-1},{0,-1},{1,-1},
			{1,0},{1,1},{0,1},{-1,1}
	};
	static int maxEat=0;
	static boolean[] deadFish;
	static int[][] fish;
	static int[][] map;
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		map = new int[4][4];
		fish = new int[17][3];
		deadFish = new boolean[17];
		for (int i = 0; i < 4; i++) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			for (int j = 0; j < 4; j++) {
			
				int num = pint(st.nextToken());
				int dir = pint(st.nextToken());
				map[i][j]=num;
				fish[num][0]=i;
				fish[num][1]=j;
				fish[num][2]=dir-1;
			}
		}
		//fish[0] = shark
		deadFish[map[0][0]]=true;
		maxEat+=map[0][0];
		fish[0][2] = fish[ map[0][0] ][2];
		map[0][0]=-1;
		
		rec(maxEat);
		System.out.println(maxEat);
	}
	
	static void rec(int eat) {
		//comparemaxEat
		if(maxEat<eat)maxEat=eat;
		
		
		int[][]tmpMap = new int[4][4];
		int[][] tmpFish = new int[17][3];
		boolean[] tmpDeadFish = new boolean[17];
		//backup
		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				tmpMap[i][j]=map[i][j];
			}
		}
		for (int i = 0; i < 17; i++) {
			tmpFish[i][0]=fish[i][0];
			tmpFish[i][1]=fish[i][1];
			tmpFish[i][2]=fish[i][2];
			tmpDeadFish[i]=deadFish[i];
		}

		//fish move
		for (int i = 1; i < 17; i++) {
			if(deadFish[i])continue;//죽었다면 넘어감
			
			int curX = fish[i][0], curY = fish[i][1], curDir = fish[i][2];
			for (int j = 0; j < 8; j++) {
				//ok?
				int nX = curX+dir[curDir][0];
				int nY = curY+dir[curDir][1];
				if(nX<0 || nY<0 || nX>=4 || nY>=4 || map[nX][nY]==-1) {
					curDir= (curDir+1)%8; continue;
				}
				
				//swap
				int tmp = map[nX][nY];
				map[nX][nY]=map[curX][curY];
				map[curX][curY]=tmp;
				
				fish[i][0]=nX;fish[i][1]=nY;
				fish[i][2]=curDir;

				if(tmp!=0) {
					fish[tmp][0]=curX;
					fish[tmp][1]=curY;
				}
				
				break;
			}
		}
		
		//shark move
		//eat
		map[ fish[0][0] ][ fish[0][1] ]=0;//빈 공간화
		while(true) {
			fish[0][0]+=dir[fish[0][2]][0];
			fish[0][1]+=dir[fish[0][2]][1];
			
			if(fish[0][0]<0 || fish[0][0]>=4 || fish[0][1]<0 || fish[0][1]>=4) {
				break;
			}
			if(map[fish[0][0]][fish[0][1]]==0)continue;
			
			int tmp = map[ fish[0][0] ][ fish[0][1] ];
			
			map[ fish[0][0] ][ fish[0][1] ]=-1;
			deadFish[tmp]=true;
			int tmpShakeDir = fish[0][2];
			fish[0][2]=fish[tmp][2];
			
			rec(eat+tmp);
			
			fish[0][2]=tmpShakeDir;
			map[ fish[0][0] ][ fish[0][1] ]=tmp;
			deadFish[tmp]=false;
		}
		
		//return
		//restore
		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				map[i][j]=tmpMap[i][j];
			}
		}
		for (int i = 0; i < 17; i++) {
			fish[i][0]=tmpFish[i][0];
			fish[i][1]=tmpFish[i][1];
			fish[i][2]=tmpFish[i][2];
			deadFish[i]=tmpDeadFish[i];
		}
		return;
	}
	
	
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과 화면

[문제링크]

 

2346번: 풍선 터뜨리기

1번부터 N번까지 N개의 풍선이 원형으로 놓여 있고. i번 풍선의 오른쪽에는 i+1번 풍선이 있고, 왼쪽에는 i-1번 풍선이 있다. 단, 1번 풍선의 왼쪽에 N번 풍선이 있고, N번 풍선의 오른쪽에 1번 풍선

www.acmicpc.net

 

1. 사용한 풍선은 표시해두고, 지나가더라도 카운트하지 않는다

 

2. 양 끝 간 이동 처리를 위해, 증감시 N으로 나머지 연산

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main{
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb = new StringBuilder();
		
		int N = pint(br.readLine());
		int[] num = new int[N];
		boolean[] chk = new boolean[N];
		
		StringTokenizer st = new StringTokenizer(br.readLine());
		for (int i = 0; i < N; i++) {
			num[i]=pint(st.nextToken());
		}
		
		int cur=0;
		sb.append(cur+1).append(" ");
		int move = num[cur];
		chk[cur]=true;
		for (int i = 1; i < N; i++) {
			int cnt=0;
			while(cnt<Math.abs(move)) {
				if(move>0) {
					cur++;
					cur%=N;
					if(chk[cur])continue;
				}
				else {
					cur--;
					cur+=N;
					cur%=N;
					if(chk[cur])continue;
				}
				cnt++;
			}
			sb.append(cur+1).append(" ");
			move = num[cur];
			chk[cur]=true;
		}System.out.println(sb);
	}
	
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과 화면

[문제링크]

 

20058번: 마법사 상어와 파이어스톰

마법사 상어는 파이어볼과 토네이도를 조합해 파이어스톰을 시전할 수 있다. 오늘은 파이어스톰을 크기가 2N × 2N인 격자로 나누어진 얼음판에서 연습하려고 한다. 위치 (r, c)는 격자의 r행 c

www.acmicpc.net

 

0. 단순 구현 + 그래프 탐색 문제

 

1. 주어진 l 값에 맞게, 각 칸을 회전시킨다

 

2. 다른 얼음과 2칸 이하로 맞닿은 칸들을 체크한다

 

3. 해당 칸들을 녹인다

 

4. 1~3 반복

 

5. 다 녹은 후 dfs를 실행, 가장 큰 덩어리의 크기를 찾는다

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main{
	static int[][]map;
	static boolean[][] chk;
	static int size;
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");
		int n = pint(st.nextToken());
		int m = pint(st.nextToken());
		size = 1<<n;
		map = new int[size][size];
		for (int i = 0; i < size; i++) {
			st = new StringTokenizer(br.readLine());
			for (int j = 0; j < size; j++) {
				map[i][j]=pint(st.nextToken());
			}
		}
		
		st = new StringTokenizer(br.readLine());
		for (int i = 0; i < m; i++) {
			int l = pint(st.nextToken());
			chk=new boolean[size][size];
			//돌리기
			divide(l);
			//녹일것찾기
			findMelt();
			//녹이기
			melt();
		}

		//dfs search
		chk=new boolean[size][size];
		int cntMax=0;
		for (int i = 0; i < size; i++) {
			for (int j = 0; j < size; j++) {
				if(!chk[i][j] && map[i][j]>0) {
					cntMax = Math.max(cntMax, dfs(i,j));
				}
			}
		}
		
		int sum=0;
		for (int i = 0; i < size; i++) {
			for (int j = 0; j < size; j++) {
				sum+=map[i][j];
			}
		}
		System.out.println(sum+"\n"+cntMax);
		
	}
	
	static int dfs(int x, int y) {
		int cnt=1;
		chk[x][y]=true;
		if(x>0 && !chk[x-1][y] && map[x-1][y]>0)cnt+=dfs(x-1,y);
		if(y>0 && !chk[x][y-1] && map[x][y-1]>0)cnt+=dfs(x,y-1);
		if(x<size-1 && !chk[x+1][y] && map[x+1][y]>0)cnt+=dfs(x+1,y);
		if(y<size-1 && !chk[x][y+1] && map[x][y+1]>0)cnt+=dfs(x,y+1);
		
		return cnt;
	}
	
	static void divide(int l) {
		int len = size / (1<<l);
		for (int i = 0; i < len; i++) {
			for (int j = 0; j < len; j++) {
				rotate(i*(1<<l), j*(1<<l), 1<<l);
			}
		}
	}
	
	static void findMelt() {
		for (int x = 0; x < size; x++) {
			for (int y = 0; y < size; y++) {
				int cnt=0;
				if(x>0 && map[x-1][y]>0)cnt++;
				if(y>0 && map[x][y-1]>0)cnt++;
				if(x<size-1 && map[x+1][y]>0)cnt++;
				if(y<size-1 && map[x][y+1]>0)cnt++;
				
				if(cnt<3 && map[x][y]>0) {
					chk[x][y]=true;
				}
			}
		}
	}
	static void melt() {
		for (int x = 0; x < size; x++) {
			for (int y = 0; y < size; y++) {
				if(chk[x][y])map[x][y]--;
			}
		}
	}
	
	static void rotate(int sx, int sy, int len) {
		if(len<=0)return;
		
		int tmp=len-1;
		int[] backup = new int[tmp];
		
		for (int i = 0; i < tmp; i++)backup[i]=map[sx][sy+i];
		
		for (int i = 0; i < tmp; i++) {
			map[sx][sy+tmp-1-i]=map[sx+i+1][sy];
		}
		for (int i = 0; i < tmp; i++) {
			map[sx+i+1][sy]=map[sx+tmp][sy+i+1];		
		}
		for (int i = 0; i < tmp; i++) {
			map[sx+tmp][sy+i+1]=map[sx+tmp-1-i][sy+tmp];
		}
		for (int i = 0; i < tmp; i++) {
			map[sx+tmp-1-i][sy+tmp]=backup[tmp-1-i];
		}
		rotate(sx+1,sy+1,len-2);
	}
	
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과 화면

[문제링크]

 

21610번: 마법사 상어와 비바라기

마법사 상어는 파이어볼, 토네이도, 파이어스톰, 물복사버그 마법을 할 수 있다. 오늘 새로 배운 마법은 비바라기이다. 비바라기를 시전하면 하늘에 비구름을 만들 수 있다. 오늘은 비바라기

www.acmicpc.net

 

0. 단순 구현 문제

 

1. 구름을 이동하고 -> 대각선 물 양을 증가시키고 -> 새 구름을 생성한다 의 반복

 

2. 구름이 사라진 칸은 boolean 배열로 관리한다

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main{
	
	static int[][] dir = new int[][]{
		{0,-1},{-1,-1},{-1,0},{-1,1},
		{0,1},{1,1},{1,0},{1,-1}
	};
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");
		int n = pint(st.nextToken());
		int m = pint(st.nextToken());
		int sum=0;
		
		int[][]map = new int[n][n];
		boolean[][]chk;
		
		for (int i = 0; i < n; i++) {
			st = new StringTokenizer(br.readLine());
			for (int j = 0; j < n; j++) {
				map[i][j]=pint(st.nextToken());
			}
		}
		
		Queue<int[]> cloud = new LinkedList<>();
		cloud.add(new int[] {n-1,0}); cloud.add(new int[] {n-1,1});
		cloud.add(new int[] {n-2,0}); cloud.add(new int[] {n-2,1});
		
		for (int i = 0; i < m; i++) {
			st = new StringTokenizer(br.readLine());
			int d = pint(st.nextToken())-1;
			int s = pint(st.nextToken());
			chk=new boolean[n][n];
			//구름 이동 페이즈
			int len = cloud.size();
			for (int j = 0; j < len; j++) {
				int[] cur = cloud.poll();
				int newX = cur[0]+dir[d][0]*s;
				int newY = cur[1]+dir[d][1]*s;
				newX = ((newX%n)+n)%n;
				newY = ((newY%n)+n)%n;
				//1증가
				map[newX][newY]++;
				cloud.add(new int[] {newX,newY});
			}
			
			//이동 후 물양 증가 페이즈
			for (int j = 0; j < len; j++) {
				int[] cur = cloud.poll();
				if(cur[0]-1>=0 && cur[1]-1>=0 && map[cur[0]-1][cur[1]-1]>0) {
					map[cur[0]][cur[1]]++;
				}if(cur[0]-1>=0 && cur[1]+1<n && map[cur[0]-1][cur[1]+1]>0) {
					map[cur[0]][cur[1]]++;
				}if(cur[0]+1<n && cur[1]-1>=0 && map[cur[0]+1][cur[1]-1]>0) {
					map[cur[0]][cur[1]]++;
				}if(cur[0]+1<n && cur[1]+1<n && map[cur[0]+1][cur[1]+1]>0) {
					map[cur[0]][cur[1]]++;
				}
				chk[cur[0]][cur[1]]=true;
			}
			
			//신규 구름 생성 페이즈
			
			for (int j = 0; j < n; j++) {
				for (int j2 = 0; j2 < n; j2++) {
					if(!chk[j][j2] && map[j][j2]>=2) {
						map[j][j2]-=2;
						cloud.add(new int[] {j,j2});
					}
				}
			}
		}
		for (int x = 0; x < n; x++) {
			for (int y = 0; y < n; y++) {
				sum+=map[x][y];
			}
		}System.out.println(sum);
		
	}
	
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과 화면

 

[문제링크]

 

17276번: 배열 돌리기

각 테스트 케이스에 대해 회전 연산을 마친 후 배열의 상태를 출력한다. n줄에 걸쳐 각 줄에 n개의 정수를 공백으로 구분하여 출력한다. 

www.acmicpc.net

 

0. 단순한 구현 문제

 

1. 4개의 대각선을 옮기는 작업을 한다

  • 두 수를 swap하듯, 하나를 백업하고 후에 복구

 

2. -X 각도로의 회전은 360-X 각도의 회전과 같다

  • 별도의 함수를 만들지 않고, 45도 회전 함수를 동일하게 사용

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main{
	static int[][] map;
	static int n,d;
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb = new StringBuilder();
		
		int tc = pint(br.readLine());
		for (int test = 1; test <= tc; test++) {
			StringTokenizer st = new StringTokenizer(br.readLine());
			n = pint(st.nextToken());
			d = pint(st.nextToken())/45;
			if(d<0)d+=8;
			map=new int[n][n];
			
			for (int i = 0; i < n; i++) {
				st = new StringTokenizer(br.readLine());
				for (int j = 0; j < n; j++) {
					map[i][j]=pint(st.nextToken());
				}
			}
			
			for (int i = 0; i < d; i++) {
				spin();
			}
			for (int i = 0; i < n; i++) {
				for (int j = 0; j < n; j++) {
					sb.append(map[i][j]).append(" ");
				}sb.append("\n");
			}
		}System.out.println(sb);
	}
	static void spin() {
		int[] backup = new int[n];
		for (int i = 0; i < n; i++)backup[i]=map[i][i];//백업
		
		for (int i = 0; i < n; i++)map[i][i]=map[n/2][i];
		for (int i = 0; i < n; i++)map[n/2][i]=map[n-i-1][i];
		for (int i = 0; i < n; i++)map[n-i-1][i]=map[n-i-1][n/2];
		for (int i = 0; i < n; i++)map[i][n/2]=backup[i];
	}
	
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과 화면

[문제링크]

 

1339번: 단어 수학

첫째 줄에 단어의 개수 N(1 ≤ N ≤ 10)이 주어진다. 둘째 줄부터 N개의 줄에 단어가 한 줄에 하나씩 주어진다. 단어는 알파벳 대문자로만 이루어져있다. 모든 단어에 포함되어 있는 알파벳은 최대

www.acmicpc.net

 

0. 각 알파벳의 총 크기를 구해, 그리디하게 숫자를 부여한다

  • ex) AB, BC의 경우, A는 10의자리에 1번 나오니 10, B는 11, C는 1
  • B가 가장 크므로 9, 그다음인 A에 8, C에 7을 주는 식

 

1. 모든 수에 대해 알파벳별로 등장 자릿수에 따라 값을 누적시킨다

 

2. 종료시 내림차순 정렬, 값이 큰 순으로 9~0까지 값을 부여하며 진행한다

  • 알파벳이 10개 이하로 존재하여도, tmp배열의 초깃값이 0이므로 문제 없음

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;

public class Main{
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		Integer[] tmp = new Integer[26];
		int N = pint(br.readLine());
		int num=9, sum=0;
		for (int i=0; i<26; i++)tmp[i]=0;
		for (int i = 0; i < N; i++) {
			String s = br.readLine();
			for (int j = 0; j < s.length(); j++)tmp[s.charAt(j)-'A']+= (int)Math.pow(10, s.length()-j-1);		
		}
		Arrays.sort(tmp, Comparator.reverseOrder());
		for (int i = 0; i < 10; i++)sum+=tmp[i]*num--;
		System.out.println(sum);
	}
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과 화면

+ Recent posts