Category Archives: DP + bitmask
12063 – Zeros and Ones
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.math.BigInteger; import java.util.Arrays; import java.util.StringTokenizer; public class ZerosAndOnes { private static long[][][] dp; private static int k; private static int n; private static int[] pow; public static void main(String[] args) throws NumberFormatException, IOException { BufferedReader buf = new BufferedReader( new InputStreamReader(System.in)); int tt = Integer.parseInt(buf.readLine()); StringBuilder ans = new StringBuilder(""); for (int t = 1; t <= tt; t++) { StringTokenizer str = new StringTokenizer(buf.readLine()); n = Integer.parseInt(str.nextToken()); k = Integer.parseInt(str.nextToken()); if (k == 0){ ans.append("Case " + t + ": 0\n"); continue; } pow = new int[64]; pow[0] = 1 % k; for (int i = 1; i < 64; i++) pow[i] = (pow[i - 1] * 2) % k; dp = new long[n][n + 1][k]; for (int i = 0; i < dp.length; i++) for (int j = 0; j < dp[0].length; j++) Arrays.fill(dp[i][j], -1); long tot = go(1, 1, 0, pow[n - 1]); ans.append("Case " + t + ": " + tot + "\n"); } System.out.print(ans); } private static long go(int index, int c1, int c0, int rem) { if (index == n && c1 == c0 && rem == 0) return 1; else if (index == n) return 0; else if (dp[index][c1][rem] != -1) return dp[index][c1][rem]; else { long tot = 0; int nextRem = pow[index - 1]; nextRem += rem; nextRem %= k; tot += go(index + 1, c1 + 1, c0, nextRem); tot += go(index + 1, c1, c0 + 1, rem); return dp[index][c1][rem] = tot; } } }
11472 – Beautiful Numbers
package DP_bitmask; import java.util.Arrays; import java.util.Scanner; public class BeautifulNumbers { public static void main(String[] args){ Scanner sc = new Scanner(System.in); int t = sc.nextInt(); while (t-- > 0) { n = sc.nextInt(); int m = sc.nextInt(); if (m < n) System.out.println(0); else { long[][][] dp = new long[m][(1 << n) + 1][21]; for (int i = 0; i < dp.length; i++) for (int j = 0; j < dp[0].length; j++) Arrays.fill(dp[i][j], -1); long sum = 0; sum += find(1, 0, 0, dp, true) % 1000000007; for (int i = 1; i < n; i++) sum += find(1, 1 << i, i, dp, false) % 1000000007; System.out.println(sum % 1000000007); } } } static int n; private static long find(int place, int bitmask, int prev, long[][][] dp, boolean leading) { if (prev == -1 || prev == n) return 0; if (place == dp.length && bitmask == (1 << n) - 1) return 1; if (place == dp.length) return 0; if (dp[place][bitmask][prev] != -1) return dp[place][bitmask][prev]; else { long sum = 0; if (prev == 0 && leading) { sum += find(place + 1, bitmask, 0, dp, true) % 1000000007; for (int i = 1; i < n; i++) sum += find(place + 1, 1 << i, i, dp, false) % 1000000007; } else { sum += find(place + 1, bitmask | (1 << (prev + 1)), prev + 1, dp, false) % 1000000007; sum += find(place + 1, bitmask | (1 << (prev - 1)), prev - 1, dp, false) % 1000000007; } return dp[place][bitmask][prev] = sum % 1000000007; } } }
10651 – Pebble Solitaire
package DP_bitmask; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Arrays; public class PebbleSolitaire { public static void main(String[] args) throws NumberFormatException, IOException { BufferedReader buf = new BufferedReader( new InputStreamReader(System.in)); int t = Integer.parseInt(buf.readLine()); while (t-- > 0) { char[] p = buf.readLine().toCharArray(); int bitmask = 0; for (int i = 0; i < 12; i++) if (p[i] == 'o') bitmask |= (1 << (11 - i)); int[] dp = new int[(1 << 12) + 1]; Arrays.fill(dp, -1); int min = find(bitmask, dp); System.out.println(min); } } private static int find(int bitmask, int[] dp) { int x = check(bitmask); if (x != -1) return x; else if (dp[bitmask] != -1) return dp[bitmask]; else { int min = 12; for (int i = 0; i < 11; i++) { if ((bitmask & (1 << i)) != 0 && (bitmask & (1 << (i + 1))) != 0) { if (i == 0) { if ((bitmask & (1 << i + 2)) == 0) { min = Math .min(min, find((((bitmask | (1 << (i + 2)))) & (~(1 << i))) & (~(1 << (i + 1))), dp)); } } else if (i == 10) { if ((bitmask & (1 << i - 1)) == 0) { min = Math .min(min, find((((bitmask | (1 << (i - 1)))) & (~(1 << i))) & (~(1 << (i + 1))), dp)); } } else { if ((bitmask & (1 << i - 1)) == 0) { int y = bitmask; y |= (1 << (i - 1)); y &= ~(1 << i); y &= ~(1 << (i + 1)); min = Math.min(min, find(y, dp)); } if ((bitmask & (1 << i + 2)) == 0) { int y = bitmask; y |= (1 << (i + 2)); y &= ~(1 << i); y &= ~(1 << (i + 1)); min = Math.min(min, find(y, dp)); } } } } return dp[bitmask] = min; } } private static int check(int bitmask) { int count = 0; for (int i = 0; i < 11; i++) { if ((bitmask & (1 << i)) == 0) count++; if ((bitmask & (1 << i)) != 0 && ((bitmask & (1 << (i + 1))) != 0)) return -1; } if ((bitmask & (1 << 11)) == 0) count++; return 12 - count; } }
10911 – Forming Quiz Teams
I got the same idea as competitive programming but instead of bitwise shifts i would have used just an array of zeros and ones but i learned how to use it 🙂
package DP_bitmask; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.math.BigDecimal; import java.util.Arrays; class FormingQuizTeams { public static void main(String[] args) throws NumberFormatException, IOException { BufferedReader buf = new BufferedReader( new InputStreamReader(System.in)); int test = 1; while (true) { int n = Integer.parseInt(buf.readLine()); if (n == 0) break; int[][] points = new int[2 * n][2]; double[] dp = new double[(int) (Math.pow(2, 2 * n) + 1)]; Arrays.fill(dp, -1); for (int i = 0; i < 2 * n; i++) { String[] line = buf.readLine().split(" "); int x = Integer.parseInt(line[1]); int y = Integer.parseInt(line[2]); points[i][0] = x; points[i][1] = y; } double min = find(0, points, dp, 2 * n); BigDecimal bd = new BigDecimal(min); bd = bd.setScale(2, BigDecimal.ROUND_HALF_UP); System.out.println("Case " + (test++) + ": " + bd); } } private static double find(int i, int[][] points, double[] dp, int m) { if (i == (1 << m) - 1) return 0; if (dp[i] != -1) return dp[i]; else { double min = Double.MAX_VALUE; for (int j = 0; j < m; j++) if ((i & (1 << j)) == 0) { for (int k = j + 1; k < m; k++) if ((i & (1 << k)) == 0) { double x = calc(j, k, points); min = Math.min( min, x + find(i | (1 << k) | (1 << j), points, dp, m)); } } return dp[i] = min; } } private static double calc(int j, int k, int[][] points) { return Math.sqrt((points[j][0] - points[k][0]) * (points[j][0] - points[k][0]) + (points[j][1] - points[k][1]) * (points[j][1] - points[k][1])); } }