[SWEA] 3234. 준환이의 양팔저울
- 메모리 : 20,512 KB
- 실행시간 : 736 ms
- 코드길이 : 1,464 B
- 소요시간 : 1H 20M
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Solution_D4_3234_준환이의양팔저울 {
static int N, cnt, sum;
static int[] m;
private static int exp[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 };
private static int fact[] = { 0, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 };
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
StringBuilder answer = new StringBuilder();
int T = Integer.parseInt(in.readLine());
for (int tc = 0; tc < T; tc++) {
N = Integer.parseInt(in.readLine());
m = new int[N];
sum = 0;
cnt = 0;
StringTokenizer st = new StringTokenizer(in.readLine(), " ");
for (int i = 0; i < N; i++) {
m[i] = Integer.parseInt(st.nextToken());
sum += m[i];
}
recur(0, 0, 0, 0);
answer.append('#').append(tc+1).append(' ').append(cnt).append('\n');
}
System.out.print(answer);
in.close();
}
private static void recur(int index, int left, int right, int flag) {
if (left < right)
return;
if (index == N) {
cnt++;
return;
}
if(left >= sum-left) {
cnt += exp[N-index]*fact[N-index];
return;
}
for (int i = 0; i < N; i++) {
if ((flag & (1 << i)) == 0) {
recur(index + 1, left + m[i], right, (flag | (1 << i)));
recur(index + 1, left, right + m[i], (flag | (1 << i)));
}
}
}
}
- 메모리 : 20,188 KB
- 실행시간 : 610 ms
- 코드길이 : 1,641 B
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Solution_D4_3234_준환이의양팔저울_개선 {
static int N, cnt, sum;
static int[] m;
private static int[] pow;
private static int[] facto;
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
StringBuilder answer = new StringBuilder();
int T = Integer.parseInt(in.readLine());
for (int tc = 0; tc < T; tc++) {
N = Integer.parseInt(in.readLine());
m = new int[N];
facto = new int[N + 1];
pow = new int[N + 1];
facto[0] = facto[1] = pow[0] = 1;
sum = 0;
cnt = 0;
StringTokenizer st = new StringTokenizer(in.readLine(), " ");
for (int i = 0; i < N; i++) {
m[i] = Integer.parseInt(st.nextToken());
sum += m[i];
facto[i + 1] = facto[i] * (i + 1);
pow[i + 1] = pow[i] * 2;
}
recur(0, 0, 0, 0, sum);
answer.append('#').append(tc + 1).append(' ').append(cnt).append('\n');
}
System.out.print(answer);
in.close();
}
private static void recur(int index, int left, int right, int flag, int remain) {
if (remain + right <= left) { // 남은 추를 다 오른쪽에 놔도 왼쪽보다 안무거울 경우 가지치기
cnt += facto[N - index] * pow[N - index];
return;
}
if (index == N) {
cnt++;
return;
}
for (int i = 0; i < N; i++) {
if ((flag & (1 << i)) == 0) {
recur(index + 1, left + m[i], right, (flag | (1 << i)), remain - m[i]);
if (right + m[i] <= left)
recur(index + 1, left, right + m[i], (flag | (1 << i)), remain - m[i]);
}
}
}
}
Leave a comment