k个样本
状态有2的k次方个
状压dp往往样本数据量都不大 20个以内
题目一
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| / 我能赢吗
public class Code01_CanIWin {
public static boolean canIWin(int n, int m) { if (m == 0) { return true; } if (n * (n + 1) / 2 < m) { return false; } int[] dp = new int[1 << (n + 1)]; return f(n, (1 << (n + 1)) - 1, m, dp); }
public static boolean f(int n, int status, int rest, int[] dp) { if (rest <= 0) { return false; } if (dp[status] != 0) { return dp[status] == 1; } boolean ans = false; for (int i = 1; i <= n; i++) { if ((status & (1 << i)) != 0 && !f(n, (status ^ (1 << i)), rest - i, dp)) { ans = true; break; } } dp[status] = ans ? 1 : -1; return ans; }
}
|
题目二
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
|
public class Code02_MatchsticksToSquare {
public static boolean makesquare(int[] nums) { int sum = 0; for (int num : nums) { sum += num; } if (sum % 4 != 0) { return false; } int n = nums.length; int[] dp = new int[1 << n]; return f(nums, sum / 4, (1 << n) - 1, 0, 4, dp); }
public static boolean f(int[] nums, int limit, int status, int cur, int rest, int[] dp) { if (rest == 0) { return status == 0; } if (dp[status] != 0) { return dp[status] == 1; } boolean ans = false; for (int i = 0; i < nums.length; i++) { if ((status & (1 << i)) != 0 && cur + nums[i] <= limit) { if (cur + nums[i] == limit) { ans = f(nums, limit, status ^ (1 << i), 0, rest - 1, dp); } else { ans = f(nums, limit, status ^ (1 << i), cur + nums[i], rest, dp); } if (ans) { break; } } } dp[status] = ans ? 1 : -1; return ans; }
}
|
题目三
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
|
public class Code03_PartitionToKEqualSumSubsets {
public static boolean canPartitionKSubsets1(int[] nums, int k) { int sum = 0; for (int num : nums) { sum += num; } if (sum % k != 0) { return false; } int n = nums.length; int[] dp = new int[1 << n]; return f1(nums, sum / k, (1 << n) - 1, 0, k, dp); }
public static boolean f1(int[] nums, int limit, int status, int cur, int rest, int[] dp) { if (rest == 0) { return status == 0; } if (dp[status] != 0) { return dp[status] == 1; } boolean ans = false; for (int i = 0; i < nums.length; i++) { if ((status & (1 << i)) != 0 && cur + nums[i] <= limit) { if (cur + nums[i] == limit) { ans = f1(nums, limit, status ^ (1 << i), 0, rest - 1, dp); } else { ans = f1(nums, limit, status ^ (1 << i), cur + nums[i], rest, dp); } if (ans) { break; } } } dp[status] = ans ? 1 : -1; return ans; }
|
题目四
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
|
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.StreamTokenizer;
public class Code04_TSP1 {
public static int MAXN = 19;
public static int[][] graph = new int[MAXN][MAXN];
public static int[][] dp = new int[1 << MAXN][MAXN];
public static int n;
public static void build() { for (int s = 0; s < (1 << n); s++) { for (int i = 0; i < n; i++) { dp[s][i] = -1; } } }
public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StreamTokenizer in = new StreamTokenizer(br); PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out)); while (in.nextToken() != StreamTokenizer.TT_EOF) { n = (int) in.nval; build(); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { in.nextToken(); graph[i][j] = (int) in.nval; } } out.println(compute()); } out.flush(); out.close(); br.close(); }
public static int compute() { return f(1, 0); }
public static int f(int s, int i) { if (s == (1 << n) - 1) { return graph[i][0]; } if (dp[s][i] != -1) { return dp[s][i]; } int ans = Integer.MAX_VALUE; for (int j = 0; j < n; j++) { if ((s & (1 << j)) == 0) { ans = Math.min(ans, graph[i][j] + f(s | (1 << j), j)); } } dp[s][i] = ans; return ans; }
}
|