状 压 d p
时间:2020-07-14
本文章向大家介绍状 压 d p,主要包括状 压 d p使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
原来一直没太搞懂,今天大力搞了搞,感觉比较可了
latex取反是\sim
\[把数拆成二进制数
所以我们最多只需要2^{n+1}-1的十进制数就好(二进制形式是n个1)\\
1.判断一个数字x二进制下第i位是不是1(假设最低为第1位)\\
if(1 << (i-1)\&x) 操作\\
2.将一个数字x二进制第i位改成1\\
x = x | (1<<(i-1))\\
3.将一个数字x二进制下第i为改成0\\
x=x\&(\sim(1<<(i-1)))取反符号是sim\\
4.将一个数二进制下最靠右的一去掉\\
x = x\&(x-1)
\]
状压里提到状态的一维肯定是1<<某某
p1896
\[互不侵犯在 n×n(1\le n\le10) 的棋盘上放 k(0\le k<n^2)个国王,国王可攻击相邻的8个格子,求使它们无法互相攻击的方案总数。\\
考虑到每行每列之间都有互相的约束关系。因此,我们可以用行和列作为另一个状态的部分。\\
我们的三个状态就有了:第几行(用i表示),此行放什么状态(用j表示),包括这一行已经使用了的国王数用s表示\\
f[i][j][s]=\sum f[i-1][k][s-num[j]]\\
首先的问题就是,上文中的k和j怎么表示?\\
假设现在第i行的放置状态是这样的:0 0 1 0 1 0 0 1(1代表有国王,0代表没有)\\
转换成十进制就是: 41(10) dp:f[i][41][s]\\
不过对于每一行的可用状态,我们可以预处理一下,预处理每一行可用可以避免麻烦,还可以优化时间复杂度。\\
预处理代码:
\]
inline void init(){
cnt=0;
for(int i=0;i<(1<<n);++i)
{
if(i&(i<<1))continue;
int sum=0;
for(int j=0;j<n;++j)
if(i&(1<<j))++sum;
s[++cnt]=i;
num[cnt]=sum;
}return;}
\[s数组时用来记录可用状态的十进制\\
num数组用来记录该状态的国王数上面例子 国王数为3\\
i是枚举所有状态数。假设n=3,那么i枚举的就是:\\
000,001,010,011,100,101,110,111\\
分别对应十进制0,1,2,3,4,5,6,7\\
所以是 i<(1<<n) (i不能到2^3(8))\\
if(i\&(i<<1))continue;判断相邻国王\\
\]
//AC代码
#include<bits/stdc++.h>
using namespace std;
int n,m,cnt,MAX;
long long dp[10][200][100];
int can[1000],num[2000];
int getsum(int x)
{
int ret=0;
while (x) ret+=(x&1),x>>=1;
return num[cnt]=ret;
}//预处理函数
int main()
{
register int i,j,k,l,x,y;
long long ans=0;
scanf("%d %d",&n,&m);
MAX=(1<<n)-1;
for (i=0;i<=MAX;i++)
if (!(i&(i<<1))) can[++cnt]=i,dp[1][cnt][getsum(i)]=1;//预处理
for (i=2;i<=n;i++)
{
for (j=1;j<=cnt;j++)
{
x=can[j];
for (k=1;k<=cnt;k++)
{
y=can[k];
if ((x&y)||(x&(y<<1))||(x&(y>>1))) continue;
for (l=0;l<=m;l++) dp[i][j][num[j]+l]+=dp[i-1][k][l];
}
}
}
for (i=1;i<=cnt;i++) ans+=dp[n][i][m];
printf("%lld",ans);
}
p3694 邦邦的大合唱站队
\[我们可以设状态i为当前已经排列好的乐队编号集合\\
sum[i][j]表示前i个人有几个属于乐队j\\
枚举l,r,则有f[i|(1<<j)]=min(f[i|(1<<j)],f[i]+(r-l-(sum[r][j]-sum[l][j])))
\]
同理eee
原文地址:https://www.cnblogs.com/shikeyu/p/13301211.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 将linux终端的输出信息保存到log中
- UNIX网络编程卷1(第三版)一个简单的时间获取服务器的程序
- Python数据分析实战(3)Python实现数据可视化
- xresloader转表工具链增加了一些新功能(map,oneof支持,输出矩阵,基于模板引擎的加载代码生成等)
- 数据结构之树
- UNIX网络编程卷1(第三版)套接字编程简介
- UNIX网络编程卷1(第三版)readn,writen和readline函数
- UNIX网络编程卷1(第三版)基本TCP套接字编程
- Ubuntu下linux映射共享盘到window下方法
- 数据同步写入磁盘:sync
- 惯用的关机命令:shutdown
- 重启、关机:reboot,halt,poweroff
- 使用Docker构建ZooKeeper镜像
- Linux进程间的通信
- 如何使用jMeter对需要CSRF token验证的OData服务进行并发性能测试