danbibibi
article thumbnail

문제

문제 바로가기> BOJ 17140번: 이차원 배열과 연산

 

17140번: 이차원 배열과 연산

첫째 줄에 r, c, k가 주어진다. (1 ≤ r, c, k ≤ 100) 둘째 줄부터 3개의 줄에 배열 A에 들어있는 수가 주어진다. 배열 A에 들어있는 수는 100보다 작거나 같은 자연수이다.

www.acmicpc.net

 

풀이

 

1. rnum(행개수) , cnum(열 개수) 변수를 이용하여 어떤 연산을 해야하는지 파악한다.

    * R 연산을 할 때 -> cnum 이 update

    * C 연산을 할 때 -> rnum 이 update

 

2.  (등장 횟수, 숫자)를 조건에 맞게 정렬하기 위해, DATA 구조체 내에서 비교 연산자를 재정의한다.

     * java의 경우 Data class를 만들고, Comparable 인터페이스를 구현

     * 벡터나 리스트에 담아서 정렬해도 상관 없을 듯 !

 

를 반영해서 문제에서 요구하는 대로 구현해주면 되는 문제였다!

 

C++

#include<iostream>
#include<cstring>
#include<queue>
#define MAX 100
#define INIT 3
using namespace std;

int R, C, K;
int cntArr[MAX+1];
int rnum=0, cnum=0;
int A[MAX][MAX], copyA[MAX][MAX];

struct DATA{
    int num, cnt;
    bool operator < (const DATA &d) const{
        if(cnt == d.cnt) return num > d.num; // 숫자 오름 차순 (2)
        else return cnt > d.cnt; // 등장 횟수 오름 차순 (1)
    }
};

void input(){
    cin >> R >> C >> K;
    for(int i=0; i<INIT; i++){
        for(int j=0; j<INIT; j++) cin >> A[i][j];
    } rnum = cnum = INIT;
}

void copy_and_init(){
    for(int i=0; i<MAX; i++){
        for(int j=0; j<MAX; j++) {
            A[i][j] = copyA[i][j];
            copyA[i][j] = 0;
        }
    }   
}

void row_operation(){ // R 연산

    int max_cnum = cnum;
    for(int r=0; r<rnum; r++){

        priority_queue<DATA> pq;
        memset(cntArr, 0, sizeof(cntArr)); // init
        for(int c=0; c<cnum; c++) cntArr[A[r][c]]++; // 등장 빈도 count
        for(int num=1; num<=MAX; num++){ // 1 ≤ k ≤ 100
            if(cntArr[num] == 0) continue; // 0은 무시
            pq.push({num, cntArr[num]}); // 숫자, 빈도
        }

        max_cnum = max(max_cnum, min(2*(int)pq.size(), MAX)); // max 값 Update

        int c = 0, cnt, num;
        while(!pq.empty() && c<MAX){ // 정렬된 값 대입
            num = pq.top().num;
            cnt = pq.top().cnt; 
            pq.pop();
            copyA[r][c++] = num;
            copyA[r][c++] = cnt;
        }
    }

    cnum = max_cnum; // max 값 반영 (가장 큰 행을 기준으로 모든 행의 크기가 변함)
}

void col_operation(){ // C 연산
    int max_rnum = rnum;
    for(int c=0; c<cnum; c++){

        priority_queue<DATA> pq;
        memset(cntArr, 0, sizeof(cntArr)); // init
        for(int r=0; r<rnum; r++) cntArr[A[r][c]]++; // 등장 빈도 count
        for(int num=1; num<=MAX; num++){ // 1 ≤ k ≤ 100
            if(cntArr[num] == 0) continue; // 0은 무시
            pq.push({num, cntArr[num]}); // 숫자, 빈도
        }

        max_rnum = max(max_rnum, min(2*(int)pq.size(), MAX)); // max 값 Update

        int r = 0, cnt, num;
        while(!pq.empty() && r<MAX){ // 정렬된 값 대입
            num = pq.top().num;
            cnt = pq.top().cnt; 
            pq.pop();
            copyA[r++][c] = num;
            copyA[r++][c] = cnt;
        }
    }

    rnum = max_rnum; // max 값 반영 (가장 큰 열을 기준으로 모든 열의 크기가 변함)
}

void solution(){
    int ans = 0;
    while(ans++ <= 100){
        if(A[R-1][C-1] == K) {
            ans--;
            break;
        }
        if(rnum >= cnum) row_operation(); // R 연산
        else col_operation(); // C 연산
        copy_and_init();
    }
    if(ans > 100) cout << -1; // 100초가 지나도 A[r][c] = k가 되지 않으면 -1을 출력
    else cout << ans; // A[r][c]에 들어있는 값이 k가 되기 위한 연산의 최소 시간  
}

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    input();
    solution();
}

 

Java

import java.io.*;
import java.util.*;

public class Main {
	
	static class Data implements Comparable<Data>{
		int num, cnt;
		
		public Data(int num, int cnt) {
			this.num = num;
			this.cnt = cnt;
		}

		@Override
		public int compareTo(Data o) {
			if(cnt == o.cnt) return num-o.num; // 숫자 오름 차순 (2)
			else return cnt-o.cnt; // 등장 횟수 오름 차순 (1)
		}
		
	}
	
	static final int MAX = 100;
	static final int INIT = 3;
	
	static int R, C, K;
	static int rnum=0, cnum=0;
	
	static int[] cntArr;
	static int[][] A = new int[MAX][MAX];
	static int[][] copyA = new int[MAX][MAX];


	public static void main(String[] args) throws Exception {
		// System.setIn(new FileInputStream("res/input.txt"));
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		R = Integer.parseInt(st.nextToken());
		C = Integer.parseInt(st.nextToken());
		K = Integer.parseInt(st.nextToken());
		
		for(int i=0; i<INIT; i++) {
			 st = new StringTokenizer(br.readLine());
			for(int j=0; j<INIT; j++) {
				A[i][j] = Integer.parseInt(st.nextToken());
			}
		} rnum = cnum = INIT;
		 
		// solution
		solution();
	}

	private static void solution() {
	    int ans = 0;
	    while(ans++ <= 100){
	        if(A[R-1][C-1] == K) {
	            ans--;
	            break;
	        }
	        if(rnum >= cnum) row_operation(); // R 연산
	        else col_operation(); // C 연산
	        copy_and_init();
	    }
	    if(ans > 100) System.out.println(-1); // 100초가 지나도 A[r][c] = k가 되지 않으면 -1을 출력
	    else System.out.println(ans); // A[r][c]에 들어있는 값이 k가 되기 위한 연산의 최소 시간  
	}

	private static void copy_and_init() {
	    for(int i=0; i<MAX; i++){
	        for(int j=0; j<MAX; j++) {
	            A[i][j] = copyA[i][j];
	            copyA[i][j] = 0;
	        }
	    }
	}

	private static void row_operation() {
	    int max_cnum = cnum;
	    for(int r=0; r<rnum; r++){

	        PriorityQueue<Data> pq = new PriorityQueue<>();
	        cntArr = new int[MAX+1];
	        for(int c=0; c<cnum; c++) cntArr[A[r][c]]++; // 등장 빈도 count
	        for(int num=1; num<=MAX; num++){ // 1 ≤ k ≤ 100
	            if(cntArr[num] == 0) continue; // 0은 무시
	            pq.add(new Data(num, cntArr[num])); // 숫자, 빈도
	        }

	        max_cnum = Math.max(max_cnum, Math.min(2*pq.size(), MAX)); // max 값 Update

	        int c = 0, cnt, num;
	        while(!pq.isEmpty() && c<MAX){ // 정렬된 값 대입
	            num = pq.peek().num;
	            cnt = pq.peek().cnt; 
	            pq.poll();
	            copyA[r][c++] = num;
	            copyA[r][c++] = cnt;
	        }
	    }

	    cnum = max_cnum; // max 값 반영 (가장 큰 행을 기준으로 모든 행의 크기가 변함)
	}
	
	private static void col_operation() {
	    int max_rnum = rnum;
	    for(int c=0; c<cnum; c++){

	    	PriorityQueue<Data> pq = new PriorityQueue<>();
	        cntArr = new int[MAX+1]; 
	        for(int r=0; r<rnum; r++) cntArr[A[r][c]]++; // 등장 빈도 count
	        for(int num=1; num<=MAX; num++){ // 1 ≤ k ≤ 100
	            if(cntArr[num] == 0) continue; // 0은 무시
	            pq.add(new Data(num, cntArr[num])); // 숫자, 빈도
	        }

	        max_rnum = Math.max(max_rnum, Math.min(2*pq.size(), MAX)); // max 값 Update

	        int r = 0, cnt, num;
	        while(!pq.isEmpty() && r<MAX){ // 정렬된 값 대입
	            num = pq.peek().num;
	            cnt = pq.peek().cnt; 
	            pq.poll();
	            copyA[r++][c] = num;
	            copyA[r++][c] = cnt;
	        }
	    }

	    rnum = max_rnum; // max 값 반영 (가장 큰 열을 기준으로 모든 열의 크기가 변함)
	}
}

'문제 풀이 > SW 역량 테스트' 카테고리의 다른 글

BOJ 15684번: 사다리 조작  (0) 2023.02.06
BOJ 17779번: 게리맨더링 2  (0) 2023.02.04
BOJ 17142번: 연구소 3  (0) 2023.02.01
BOJ 16235번: 나무 재테크  (0) 2023.01.31
BOJ 16234번: 인구 이동  (1) 2023.01.30
profile

danbibibi

@danbibibi

꿈을 꾸는 시간은 멈춰 있는 것이 아냐 두려워하지 마 멈추지 마 푸른 꿈속으로