【算法笔记】状态压缩dp(noip)

 在acwing学习算法的一点思考和总结


 状态压缩dp可以用来解决两种问题:一种是棋盘式的,也就是表示一行有2^N种摆法,另一种是表示一类集合

状压——棋盘式

 思路:可以类比一下蒙德里安的梦想的解题过程,每一行的状态都只会受到上一层状态的影响。那么我们在更新第i行的状态时,我们枚举一下第i - 1行的状态。也就是当这两行的对应状态是个合法状态的话,我们就进行方案数的累加。

确定状态转移方程:f[i][a] += f[i-1][b],表示前i行,并且第i行是第j种摆法 的最大种植方案数

预处理:为了判断哪两种行状态是对应合法的,我们需要进行预处理,找出相邻两行能进行转移的状态(二进制表达)。具体题目具体分析,在这个题目中,第一要满足左右相邻不能都是1,第二要满足上下相邻不能都是1

/*
前i行,并且第i行是第j种摆法 的最大种植方法
*/
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>using namespace std;
const int N = 14, M = 1<<12, mod = 1e8;
vector<int> head[M]; //存储合法的转移状态
vector<int> state;
int f[N][M];
int n,m;
int g[N];bool check(int x)
{for(int i = 0; i < m; i ++){if(( (x >> i) & 1) && (x>> (i+1) & 1) )return false;}return true;
}int main()
{cin>>n>>m;for(int i = 1; i <= n; i ++)for(int j = 0; j < m; j ++){int t;cin>>t;g[i] += !t * (1 << j);            }for(int i = 0; i < 1<<m; i ++ ){if(check(i)){state.push_back(i); //初次筛选:左右相邻不能同时为1}}for(int i = 0; i < state.size(); i ++){for(int j = 0; j < state.size(); j ++){int a = state[i], b = state[j];if( (a & b) == 0) //上下相邻不能同时为1{head[i].push_back(j); //若是合法就加入到可转移数组中}}}f[0][0] = 1;for(int i = 1; i <= n + 1; i ++){for(int a = 0; a < state.size(); a ++){if(!(state[a] & g[i]))for(int b : head[a])f[i][a] =(f[i][a] + f[i-1][b]) % mod;}}cout<<f[n+1][0];}

状压——集合

所有小猪击中状态由一串二进制数来表达,若一个小猪能被击中,那么该小猪对应到二进制表达上的位置就制成1。那么我们接下来要做的就是枚举所有抛物线,并求一下抛物线能击中哪些小猪。并将这个结果存放在path数组里。

state: 二进制表达式,如1100,表示前两只小猪没被击中,后两只被击中了

path[i][j] = state : 含义:经过点i和j的抛物线; 属性:遗传二进制数,表示所有小猪的状态

f[i]: i其实就是state,从0~2^N枚举i的二进制表达,直到枚举到111111(所有位上都是1时)说明所有小猪均已经被击落。 那么f[i]的含义就是所有小猪在该状态下最少可以用多少条抛物线覆盖

那么接下来就是枚举所有状态下的小猪的覆盖方式,更新最小覆盖的抛物线数量

#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>#define x first
#define y secondusing namespace std;
typedef pair<double, double> PDD;
const int N = 18, M = 1<<18;
const double eps = 1e-8;
int f[M];
PDD q[N];
int path[N][N];
int n,m;int cmp(double x, double y)
{if(fabs(x - y) < eps) return 0;if(x < y) return -1;return 1;
}int main()
{int T;cin>>T;while(T--){cin>>n>>m;for(int i = 0; i<n; i ++) cin>>q[i].x>>q[i].y;memset(path, 0, sizeof path);for(int i = 0; i < n; i ++)  //枚举所有的二次函数方程(两点确定一个抛物线,因为抛物线过原点),这里是找第一个点{path[i][i] = 1 << i;for(int j = i; j < n; j ++) //找这个函数的第二个点{double x1 = q[i].x, x2 = q[j].x;double y1 = q[i].y, y2 = q[j].y;if(!cmp(x1,x2)) continue;double a = (y1 / x1 - y2 / x2) / (x1 - x2); //通过两点,解出抛物线方程double b = y1 / x1 - a * x1;if(cmp(a, 0) >= 0) continue;int state = 0;for(int k = 0; k < n; k ++) //计算有多少点在这条抛物线上{   double x = q[k].x, y = q[k].y;if(!cmp(a*x*x + b * x, y)) state +=1 << k;}path[i][j] = state;}}memset(f, 0x3f, sizeof f);f[0] = 0;                          for(int i = 0; i < 1<<n; i ++) //枚举所有小猪击中状态{int x = 0;for(int j = 0; j < n; j ++) //若找到没被击中的小猪,那就要更新f[i]。{if(!( i >> j & 1)){x = j;break; //注意到这里是break,即只用更新一次,因为后面还会进行一次更新,避免掉重复的更新工作}}for(int k = 0; k < n; k ++){f[i | path[x][k]] = min(f[i | path[x][k]], f[i] + 1);}}cout<<f[(1<<n) - 1]<<endl;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/343928.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java面试题(java高级面试题)

线程池的核心线程数设置为多大比较合理&#xff1f; Worker线程在执行的过程中&#xff0c;有一部计算时间需要占用CPU&#xff0c;另一部分等待时间不需要占用CPU&#xff0c;通过量化分析&#xff0c;例如打日志进行统计&#xff0c;可以统计出整个Worker线程执行过程中这两…

记一次生产事故排查

背景&#xff1a;刚接手一个新工程&#xff0c;是一个给国内top级医院开发的老项目&#xff0c;因为历史原因&#xff0c;代码质量略低&#xff0c;测试难度略高。 上线很久的功能&#xff0c;最近一直频繁的爆发各种问题&#xff0c;经排查发现都是因为在业务过程中im聊天账号…

AOT-GAN-for-Inpainting项目解读|使用AOT-GAN进行图像修复

项目地址&#xff1a; https://github.com/researchmm/AOT-GAN-for-Inpainting 基于pytorch实现 论文地址&#xff1a; https://arxiv.org/abs/2104.01431 开源时间&#xff1a; 2021年 项目简介&#xff1a; AOT-GAN-for-Inpainting是一个开源的图像修复项目&#xff0c;其对 …

计算机毕业设计----Springboot超市订单管理系统

项目介绍 该超市订单管理毕业设计基于jdk8版本开发&#xff0c;在部署时需要使用jdk8以上的版本。使用了目前流行的框架组合springbootmybatis的框架技术&#xff0c; 实现了供应商管理对供应商实现增删改查、订单管理对超市订单实现增删改查、用户管理等功能&#xff0c;适用…

二十三、关于vite项目中无法使用minio的解决方案

问题背景 项目需要上传大文件,既然是大文件,如果一次性进行读取发送、接收都是不可取的,很容易导致内存问题。所以对于大文件上传,就一定要实现切片上传、断点续传。如果自己实现相对比较麻烦,但好消息是我们的文件服务使用了开源的minio作为对象存储服务,并且minio也提…

如何使用CentOS系统中的Apache服务器提供静态HTTP服务

在CentOS系统中&#xff0c;Apache服务器是一个常用的Web服务器软件&#xff0c;它可以高效地提供静态HTTP服务。以下是在CentOS中使用Apache提供静态HTTP服务的步骤&#xff1a; 1. 安装Apache服务器 首先&#xff0c;您需要确保已安装Apache服务器。可以使用以下命令安装Ap…

Linux第29步_虚拟机连接(与主机断开连接)U盘选项为灰色解决方法

在WIN11中&#xff0c;虚拟机“连接(与主机断开连接)U盘”选项为灰色&#xff0c;解决方法如下&#xff1a; 1、关闭虚拟机电源&#xff0c;得到下面的界面&#xff1a; 2、根据上述提示&#xff0c;找到虚拟机所在磁盘 3、配置文件属性见下图&#xff1a; 4、使用记事本打开…

Tomcat性能优化学习

Tomcat 服务器是一个开源的轻量级Web应用服务器&#xff0c;在中小型系统和并发量小的场合下被普遍使用&#xff0c;是开发和调试Servlet、JSP 程序的首选。相信大家对于 Tomcat 已经是非常熟悉了&#xff0c;本篇将介绍tomcat的常见优化。那么为什么要对tomcat进行优化呢。因为…

Qt QGraphicsItem获取鼠标位置对应图像坐标

本次使用了QGraphicsView来加载图像&#xff0c;然后给其设置了一个QGraphicsScene场景&#xff0c;再给场景添加了一个自定义的QGraphicsItem&#xff0c;在其中重写了paint事件&#xff0c;用来重绘图像。 正常情况时&#xff0c;QGraphicsItem上图像的有效区域QRect大小和QG…

【DotNetGuide】C#/.NET/.NET Core学习、工作、面试指南

&#x1f431;‍&#x1f680;C#/.NET/.NET Core学习、工作、面试指南 “ 让现在的自己不再迷茫✨✨✨。 GitHub开源地址&#xff1a;https://github.com/YSGStudyHards/DotNetGuide &#x1f4da;DotNetGuide简介 现如今网上关于Java、前端、Android、Golang...等相关技术的…

ssm基于Javaweb的网上奶茶店系统的设计与实现论文

摘 要 计算机网络发展到现在已经好几十年了&#xff0c;在理论上面已经有了很丰富的基础&#xff0c;并且在现实生活中也到处都在使用&#xff0c;可以说&#xff0c;经过几十年的发展&#xff0c;互联网技术已经把地域信息的隔阂给消除了&#xff0c;让整个世界都可以即时通话…

Tomcat基础升华学习

01 What is Tomcat 1.1 Tomcat官网 官网 &#xff1a;https://tomcat.apache.org 1.2 Understand 为什么说Tomcat是Servlet之类技术的实现&#xff1f; 在我们的理解中&#xff0c;Tomcat可以称为Web容器或者Servlet容器 不妨通过手写一个Tomcat来推导一下 1.2.1 创建Tomc…