当前位置: 首页 > article >正文

状压DP

状压DP

对于数据范围n<=20的可以考虑状压DP

1.蒙德里安的梦想

题目描述

求把 N × M N×M N×M 的棋盘分割成若干个 1×2 的的长方形,有多少种方案。

例如当$ N=2,M=4$ 时,共有 5 种方案。当 N = 2 , M = 3 N=2,M=3 N=2M=3 时,共有 3 种方案。

如下图所示:

2411_1.jpg

输入格式

输入包含多组测试用例。

每组测试用例占一行,包含两个整数 N 和 M。

当输入用例 N=0,M=0 时,表示输入终止,且该用例无需处理。

输出格式

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

数据范围

1 ≤ N , M ≤ 11 1≤N,M≤11 1N,M11

输入样例

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

分析

状压DP模板题,本题若横着放的长方形确定,其他就只能竖着放,所以我们只需要考虑横着放的所有状态,定义f[i,j]为第i列伸出到第i+1列的状态为j的方案数,对于状压DP,每次假定前一个状态为k,则k为第i-1列伸到第i列的状态,枚举所有的j和k,判断是否符合条件即可

这里的条件是

  • j和k的每一位不能同时为1,否则会出现长度为3的长方形: j & k = = 0 j\&k==0 j&k==0

  • 第i列不能出现连续的奇数空,这里我们会出现一个问题,如何求第i列的状态,很容易想道第i列的状态是由第i-1伸到第i列和第i列伸到第i+1列共同引起的,所以第i列状态为 j ∣ k j|k jk,对于每一列的状态,我们可以预处理一个st数组,届时判断 s t [ j ∣ k ] st[j|k] st[jk]是否为真即可

代码
#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N=12,M=(1<<11)+10;
int dp[N][M];
bool st[M];
void init(int n)
{
    
    for(int i=0;i<1<<n;i++)
    {
        st[i]=true;
        int cnt=0;
        for(int j=0;j<n;j++)
        {
            int k=i>>j&1;
            if(k)
            {
                if(cnt&1) st[i]=false;
                cnt=0;
            }
            else cnt++;
        }
        if(cnt&1) st[i]=false;
    }
}
signed main()
{
    int n,m;
    while(cin>>n>>m)
    {
        if(n==0&&m==0) break;
        init(n);
        memset(dp,0,sizeof(dp));
        dp[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((k&j)==0&&st[k|j]==true)
                    {
                        dp[i][j]+=dp[i-1][k];
                    }
                }
            }
        }
        cout<<dp[m][0]<<endl;
    }
    return 0;
}

2.最短哈密顿距离

题目描述

给定一张 n 个点的带权无向图,点从 0 ∼ n − 1 0∼n−1 0n1 标号,求起点 0 到终点 n − 1 n−1 n1的最短 Hamilton 路径。

Hamilton 路径的定义是从 0 0 0 到 n−1不重不漏地经过每个点恰好一次。

输入格式

第一行输入整数 n n n

接下来 $n $行每行 n n n 个整数,其中第 i i i 行第$ j 个整数表示点 个整数表示点 个整数表示点 i$ 到 $j 的距离(记为 的距离(记为 的距离(记为 a[i,j]$)。

对于任意的 x , y , z x,y,z x,y,z,数据保证 a [ x , x ] = 0 , a [ x , y ] = a [ y , x ] a[x,x]=0,a[x,y]=a[y,x] a[x,x]=0a[x,y]=a[y,x] 并且$ a[x,y]+a[y,z]≥a[x,z]$。

输出格式

输出一个整数,表示最短 Hamilton 路径的长度。

数据范围

1 ≤ n ≤ 20 1≤n≤20 1n20
0 ≤ a [ i , j ] ≤ 1 0 7 0≤a[i,j]≤10^7 0a[i,j]107

输入样例

5
0 2 4 5 1
2 0 6 5 3
4 6 0 8 3
5 5 8 0 5
1 3 3 5 0

输出样例

18

分析

定义 f [ i , j ] f[i,j] f[i,j]为以j为终点,通过路径状态压缩后为i的所有方案,最终答案是 f [ 1 < < n − 1 ] [ n − 1 ] f[1<<n-1][n-1] f[1<<n1][n1],用k表示前一个状态,枚举所有的j,i,k,判断i内是否包含终点j和前一个点k,若包含,则 f [ i , j ] = M i n ( f [ i , j ] , f [ i − { j } ] [ k ] + a [ k , j ] ) f[i,j]=Min(f[i,j],f[i-\{j\}][k]+a[k,j]) f[i,j]=Min(f[i,j],f[i{j}][k]+a[k,j])

代码

#include<bits/stdc++.h>

#define int long long

using namespace std;

const int N=20,M=(1<<20)+10,inf=LLONG_MAX/2;

int f[M][N];
int a[N][N];
signed main()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            cin>>a[i][j];
    
    int res=inf;
    memset(f,0x3f,sizeof(f));
    f[1][0]=0;
    int cnt=0;
    for(int j=1;j<n;j++)
    {
        for(int i=0;i<1<<n;i++)
        {
            if(i&1==0) continue;
            if(i>>j&1)
            {
                for(int k=0;k<n;k++)
                {
                    if(i>>k&1)
                    {
                        f[i][j]=min(f[i][j],f[i-(1<<j)][k]+a[k][j]);
                    }
                }
            }
        }
    }
    cout<<f[(1<<n)-1][n-1]<<endl;
        
    return 0;
}

http://www.kler.cn/news/293112.html

相关文章:

  • docker容器命令汇总(全)
  • 投资 - 什么是空中成交
  • CleanMyMac X2024破解激活码许可证号码
  • Flutter【03】图片输出package依赖关系
  • Alternative account/备选科目代码配置说明 【1:1和国家科目配置运营科目】
  • Uniapp基础学习(二)
  • 前端---对MVC MVP MVVM的理解
  • 在postman中使用javascript脚本生成sign签名
  • VBA语言専攻T3学员领取资料通知
  • 我父母对AI不太信任,直到我给他们展示了这7款应用
  • Datawhale X 李宏毅苹果书 AI夏令营 进阶 Task3-批量归一化+卷积神经网络
  • 【2024数模国赛赛题思路公开】国赛B题思路丨附可运行代码丨无偿自提
  • [数据集][目标检测]玉米病害检测数据集VOC+YOLO格式6000张4类别
  • 分布式:浅谈幂等
  • 浅谈城市地铁智能照明系统的能耗分析及节能措施
  • 深度学习应用 - 大规模深度学习篇
  • pytorch pyro 贝叶斯神经网络 bnn beyesean neure network svi ​定制SVI目标和培训循环,变更推理
  • 算法day16|654.最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树
  • 救命!我已经彻底被最近的FLUX模型征服了
  • 东南大学研究生-数值分析上机题(2023)Python 3 线性代数方程组数值解法
  • 初始MYSQL数据库(2)——创建、查询、更新、删除数据表的相关操作
  • python语言读入Excel文件
  • C++复习day05
  • Selenium分布式测试和操作监听
  • AUTOSAR开源OS——Trampoline的编译与使用(一)
  • Hive的存储格式
  • 晨控CK-FR08与汇川5U系列PLC配置EtherNet/IP通讯连接手册
  • MySQL的知识阶段小总结
  • k8s服务发布Ingress
  • 【高级编程】万字整理集合框架 迭代器 泛型(含方法案例)