[SWEA 3234] 준환이의 양팔저울

업데이트:

문제

  • SWEA 3234
  • 문제의 저작권은 SW Expert Academy에 있습니다.

접근방식

접근 방식은 크게 순열을 구한 후, 이 순열을 왼쪽에 넣는 경우와 오른쪽에 넣는 경우로 나누어 생각할 수 있다.
그래서 함수를 두개 만들 수 있지만 아래 코드는 합쳐진 코드이다. 그런데 의문인 것은 static변수로 선언했을 때는 시간초과가 나와서 테케 1개가 pass가 되지 않았다. 그래서 구글링한 후 local변수로 바꿔주니 통과했다. 아직 알쏭달쏭 한데 계속해서 주기적으로 풀어봐야할 문제이다.

  • 풀이 동영상을 찾았는데 다음에 풀때는 영상을 참고하고 백지상태에서 다시 풀어보자.

코드

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;

//준환이의 양팔저울
public class Solution {

	static int Ans; // 정답: 경우의 수

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		StringTokenizer st;
		int T = Integer.parseInt(br.readLine());

		for (int tc = 1; tc <= T; tc++) {
			int N = Integer.parseInt(br.readLine()); //추의 개수 
			int[] weight = new int[N];
			Ans = 0;
			boolean[] visited = new boolean[N];

			st = new StringTokenizer(br.readLine());
			for (int i = 0; i < N; i++) {
				weight[i] = Integer.parseInt(st.nextToken());
			}

			calc(weight, 0, 0, 0, visited); // 계산 시작
			System.out.println("#" + tc + " " + Ans);
		}
	}

	//순열을 구하고 양팔저울에 올리는 시도를 한번에 합침 => static변수 사용하면 시간초과뜸
	private static void calc(int[] weight, int cnt, int left, int right, boolean[] visited) { // 뽑은 추 개수, 왼쪽 합, 오른쪽 합
		//N번 다 뽑았는지 확인하기 전에 얘가 첫 조건이어야함!!
		if (left < right) { // 지금 뽑은 추의 오른쪽이 왼쪽보다 크다면
			return; // 이 경우는 고려x
		}
		
		if (cnt == weight.length) { // N번 다 뽑았으면
			Ans++; //답을 하나 증가
			return;
		}

		for (int i = 0; i < weight.length; i++) {
			if (visited[i])
				continue; // 이미 뽑은 추라면 넘어감
			visited[i] = true; // 추를 선택해서
			calc(weight, cnt + 1, left + weight[i], right, visited); // 왼쪽에 넣는 방법
			//여기서 false를 하게 되면 왼쪽에 넣은 값을 오른쪽에서 또 넣을 수 있다.
			calc(weight, cnt + 1, left, right + weight[i], visited); // 오른쪽에 넣는 방법
			visited[i] = false;
		}
	}
}