算法基础之蒙德里安的梦想

news/2024/7/15 18:37:40 标签: 算法, c++, 图论, 开发语言, 数据结构

蒙德里安的梦想

  • 核心思想: 状态压缩dp

    • 总方案 = 横放的方案 剩下的地方竖着放是固定的了

    • 状态压缩 : 将每一列的图(横终点 横起点 竖) 用一个二进制数存下

      • 向后凸的为1 反之为0
      • 在这里插入图片描述
    • 状态计算: 所有 i – 1 列 不冲突的 都加和

      • f[i , j] = f[i - 1 , k] + …. + …
      • 在这里插入图片描述
    • **不合法状态:**前两种合法 后两种不合法 单个格子不能竖放

      • 在这里插入图片描述
    • 不冲突状态:j & k ==0 没重叠部分j | k 必须是合法的

      • 在这里插入图片描述

朴素版

  •   #include<iostream>
      #include<cstring>
      #include<algorithm>
      
      using namespace std;
      const int N = 12 , M = 1 << N ;  //M为图的最大数 2的N次方
      
      int n,m;
      long long f[N][M];  //开long long的f存
      bool st[M];  //标记该图是否合法
      
      int main()
      {
          while(cin>>n>>m , n || m)  //有输入 且均不为0
          {
              for(int i=0;i< 1 << n ; i++)  //i<2的n次方
                  //一共n行 每个位置两种选择 共2的n次方
              {
                  int cnt = 0;  //记录一张图连续的0有多少个
                  st[i] = true;  //初始i图为true合法的
                  for(int j=0;j<n;j++)  //遍历图中每位数
                  {
                      if(i >> j & 1)  //取i图中第j个数 判断是否为1
                      {  //若为1 则判cnt是奇数偶数
                          if(cnt & 1)  //奇数则说明 图不合法
                          {
                              st[i] = false; //有奇数0 直接false 退出循环
                              break;
                          }
                          cnt = 0 ;  //清空cnt 重新开始
                      }
                      else cnt++;  //若为0 cnt++
                  }
                  if(cnt & 1) st[i] = false;  //判断后段0的个数 没有1 进不去上面的判断 
              }
              
              memset(f,0,sizeof f);  //初始化
              f[0][0] = 1;  //0列 不放方块 方案 = 1
              for(int i=1;i<=m;i++)  //遍历每一列
                  for(int j=0;j< 1 << n; j++)  //每列2的n次方张图
                      for(int k=0;k< 1 << n;k++)  //前一列也是2的n次方张图
                          if((j & k) == 0 && st[j | k])  //不冲突的条件
                              f[i][j] += f[i-1][k];  //计算
              cout<<f[m][0]<<endl;  //输出前m-1列排好序 没有凸出来的方案数
          }
      }
    

优化版

  •   #include<iostream>
      #include<cstring>
      #include<algorithm>
      #include<vector>
      
      using namespace std;
      const int N = 12 , M = 1 << N ;
      
      int n,m;
      long long f[N][M];
      bool st[M];
      vector<vector<int>> state(M);  //用二维数组将与 j 不冲突的k存下 不用去再遍历了
      
      int main()
      {
          while(cin>>n>>m , n || m)
          {
              for(int i=0;i< 1 << n ; i++)
              {
                  int cnt = 0;
                  st[i] = true;
                  for(int j=0;j<n;j++)
                  {
                      if(i >> j & 1)
                      {
                          if(cnt & 1)
                          {
                              st[i] = false;
                              break;
                          }
                          cnt = 0 ;
                      }
                      else cnt++;
                  }
                  if(cnt & 1) st[i] = false;
              }
              
              for(int j=0;j< 1<<n;j++)
              {
                  state[j].clear();  //清空之前的
                  for(int k=0;k< 1<<n;k++)
                  {
                      if((j & k) == 0 && st[j | k])
                          state[j].push_back(k);  //不冲突放里头
                  }
              }
              memset(f,0,sizeof f);
              f[0][0] = 1;
              for(int i=1;i<=m;i++)
                  for(int j=0;j< 1 << n; j++)
                      for(auto k : state[j])  //不冲突的已经存起来了 取出
                          f[i][j] += f[i-1][k];
              cout<<f[m][0]<<endl;
          }
      }
    

http://www.niftyadmin.cn/n/5294520.html

相关文章

mfc100u.dll文件丢失了要怎么解决?修复mfc100u.dll详细指南

mfc100u.dll文件丢失了要怎么解决?首先让我们扒一扒什么是 mfc100u.dll。这玩意儿是 Microsoft Visual Studio 2010 的一部分&#xff0c;它就像一款程序生活中不可或缺的零件&#xff0c;没了它&#xff0c;程序肯定跑不起来。想想看&#xff0c;没有一个重要的零件&#xff…

Java实现短信发送业务

1、业务需求 发送短信功能是一个很普遍的需求&#xff0c;比如验证码&#xff0c;快递单号&#xff0c;通知信息一类。 而在Java中实现短信功能相对简单&#xff0c;只需要调用短信服务商提供的API。接下来以阿里云为例&#xff0c;介绍如何实现短信发送功能&#xff0c;其他短…

CSS 缩减中心动画

<template><!-- mouseenter"startAnimation" 表示在鼠标进入元素时触发 startAnimation 方法。mouseleave"stopAnimation" 表示在鼠标离开元素时触发 stopAnimation 方法。 --><!-- 容器元素 --><div class"container" mou…

VistualStudio查看类图UML

点击菜单栏中的工具–》获取工具和功能。 然后在资源管理器中对应的代码中鼠标右键选择查看类图 生成一个ClassDiagram.cd文件就是类图的文件了。 根据需要拖拽就可以生成类图了。

免费HTTPS协议

HTTPS协议是在HTTP协议的基础上引入了SSL/TLS协议&#xff0c;通过加密传输数据&#xff0c;有效防范了中间人攻击和信息泄露。这一层加密保护使得敏感信息如登录凭证、支付数据等在传输过程中免受窥探和篡改。 主流浏览器和搜索引擎纷纷推动采用HTTPS&#xff0c;使其逐渐成为…

如何在 Ubuntu 16.04 上使用 Minio 设置对象存储服务器

前些天发现了一个人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;最重要的屌图甚多&#xff0c;忍不住分享一下给大家。点击跳转到网站。 介绍 从基于云的备份解决方案到高可用性内容交付网络 (CDN)&#xff0c;对象存储已成为现代技术领域不可或缺的…

双击编辑el-table的单元格数据

(1) el-table刷新要求绑定el-table的key要发生变化才会刷新 (2) 单元格双击事件 cell-dblclick (3) 往row里面添加一个属性来唯一标识某一行的数据&#xff0c;双击时使这特殊属性为true&#xff0c;输入框失去焦点时则设置特殊属性为false&#xff0c;并且输入框的显示与隐藏…

win/linux 环境查看动态库包含的函数

我们打包了动态库&#xff0c;还要查看是否包含一些函数&#xff0c;需要导出这些函数 在win 环境下可以使用 .def 格式的文件进行操作 ######################################################### 跳过这一步&#xff0c;回到主题&#xff0c;在两个系统平台如何查看动态库包…