Acwing.291 蒙德里安的梦想

题目

求把NM的棋盘分割成若干个12的的长方形,有多少种方案。
例如当N=2,M=4时,共有5种方案。当N=2,M=3时,共有3种方案。如下图所示:
在这里插入图片描述

输入格式

输入包含多组测试用例。
每组测试用例占一行,包含两个整数N和M。
当输入用例N=0,M=0时,表示输入终止,且该用例无需处理。

输出格式

每个测试用例输出一个结果,每个结果占一行。

数据范围

1 ≤N, M ≤11

  • 输入样例:
1 2
1 3
1 4
2 2
2 3
2 4
2 11
4 11
0 0
  • 输出样例:
1
0
1
2
3
5
144
51205

题解

import java.util.Arrays;
import java.util.Scanner;

/**
 * @author akuya
 * @create 2023-07-27-22:39
 */
public class dream {
    static int n,m;
    static int N=12;
    static int M=1<<N;
    static long f[][]=new long[N][M];
    static boolean st[]=new boolean[M];

    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);
        n=scanner.nextInt();
        m=scanner.nextInt();
        while(n!=0||m!=0){
            for(int i=0;i<N;i++){
                Arrays.fill(f[i],0);
            }

            for(int i=0;i<1<<n;i++){
                st[i]=true;
                int cnt=0;
                for(int j=0;j<n;j++)
                    if((i>>j&1)!=0){
                        if((cnt&1)!=0)st[i]=false;
                        cnt=0;
                    }else{
                        cnt++;
                    }

                if((cnt&1)!=0) st[i]=false;
            }

            f[0][0]=1;
            for(int i=1;i<=m;i++)
                for(int j=0;j<1<<n;j++)
                    for(int k=0;k<1<<n;k++)
                        if((j&k)==0&&st[j|k])
                            f[i][j]+=f[i-1][k];


            System.out.println(f[m][0]);
            n=scanner.nextInt();
            m=scanner.nextInt();
        }
    }
}

思路

本题是一道状态压缩类的动态规划问题,总的摆法,就是12小方块的摆法。刚开始接触会觉得较难,我们建立f[m][j]的冬天数组,m是纵坐标,j是点前纵坐标在被前一个纵坐标所插入的12的小方块所对应的位置为1,其余位置为0所形成的二进制数。
在满足如下如1,2两点情况的转移方程满足题目要求。
Acwing.291 蒙德里安的梦想_第1张图片

你可能感兴趣的:(java算法实录,动态规划,算法)