典型状压dp

普通状态压缩dp求方案数 玉米田

带个数限制的状态压缩dp求方案数 小国王

多行渗透的状态压缩 求最大放置个数 炮兵阵地

  1. import java.io.*;
  2. public class Main{
  3. static int[][][] f = new int[2][1 << 12][1 << 12];
  4. static int m, n;
  5. static int[] w;
  6. static ArrayList<Integer> state = new ArrayList<Integer>();
  7. public static void main(String args[]){
  8. Scanner scan = new Scanner(System.in);
  9. m = scan.nextInt(); n = scan.nextInt();
  10. w = new int[m + 3];
  11. String tmp;
  12. for (int i = 1; i <= m; i ++){
  13. tmp = scan.next();
  14. for (int j = 0; j < n; j ++){
  15. if (tmp.charAt(j) == 'H')
  16. w[i] += (1 << (n - 1 - j));
  17. }
  18. }
  19. for (int i = 0; i < 1 << n; i ++){
  20. if (check(i) == true) state.add(i);
  21. }
  22. //三层,用head只能保证两层的关系
  23. for (int i = 1; i <= m + 2; i ++){
  24. for (Integer j : state){
  25. if ((w[i] & j)!= 0)continue;
  26. for (Integer k : state){
  27. for (Integer p : state){
  28. if ((j & k | k & p | p & j) == 0)
  29. f[i & 1][j][k] = Math.max(f[i & 1][j][k], f[i - 1 & 1][k][p] + count(j));
  30. }
  31. }
  32. }
  33. // System.out.println("第" + i + "行:" + f[i][0][0]);
  34. }
  35. System.out.println(f[m + 2 & 1][0][0]);
  36. }
  37. public static boolean check(int k){
  38. for (int i = 0; i < n; i ++){
  39. if ((k >> i & 1) == 1 && ( (k >> (i + 1) & 1) == 1 || (k >> (i + 2) & 1) == 1 ) ) return false;
  40. }
  41. return true;
  42. }
  43. public static int count(int k){
  44. int res = 0;
  45. for (int i = 0; i < n; i ++)
  46. res += (k >> i & 1) ;
  47. return res;
  48. }
  49. }

愤怒的小鸟(难度较大)

蒙德里安的梦想

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

//state 定义的是从i-1列伸到i列的状态,因此要计算
public class Main{
    static int n, m, T;
    static int[][]f = new int[15][1 << 15];
    static ArrayList<Integer> state = new ArrayList<Integer>();
    public static void main(String args[]){
        Scanner scan = new Scanner(System.in);
        while (true){
            state.clear();
            m = scan.nextInt(); n = scan.nextInt();
            for (int i = 0; i < m; i ++)
                Arrays.fill(f[i], 0);
            if (n == 0 && m == 0) break;
            int cnt = 0;
            for (int i = 0; i < 1 << m; i ++){
                boolean flag = true; cnt = 0;
                for (int j = 0; j < m; j ++){
                    if ((i >> j & 1) == 1){
                        if (cnt % 2 == 1){
                            cnt = 0;
                            flag = false;
                        }
                    }else
                        cnt++;
                }
                if (cnt % 2 == 1)flag = false;
                if (flag == true) state.add(i);
            }    
            /*for (Integer s : state)
                System.out.print(s + " ");
            System.out.println();  */
            f[1][0] = 1;
            for (int i = 1; i <= n + 1; i ++){
                for (Integer s : state){
                    for (Integer k : state){
                        if ((s & k) == 1)continue;
                        f[i][s] += f[i - 1][k];
                    }
                }
            }
            System.out.println(f[n + 1][0]);
        }
    }
}

LeetCode