二:状压dp

一:状压dp的基本特征

状态压缩问题一般是指用十进制的数来表示二进制下的状态

这种用一个数来表示一组数,以降低表示状态所需的维数的解题手段,就叫做状态压缩。

常用到位运算

二:位运算

&:与运算,相同为1不同为0

| :或运算,全0位0,否则为1

^:异或运算,不同为1,相同为0(也叫半加与运算)

<<:左移操作,x<<j,x在二进制下向左移j位,(也就是原来的数乘j即:x*=j)右边用0填充,反码不同,要用1填充(负数)

>>:右移操作,x>>j相当于x=/j,左边反码,补码补1(负数)

例:

1.判断一个数字x在二进制下的第i位是不是为1if(((i<<(i-1))&x)>0)

将1左移i-1位,相当于制造了一个只有第i位为1其他位都是0的二进制数,然后用该数与x做与运算

2.把一个数字x在二进制下的第x为更改为1

x|=(1<<(i-1))

eg:

有一个n*m的棋盘(1<=n<=5,1<=m<=1000)现有1*2和2*1的小木块无数

要想盖满整个棋盘有多少种方法,答案大于1000000007,mod1000000007。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
int N, M;    //n,m分别代表棋盘的长宽
long long dp[1005][34];    //dp[i][j]表示对于前i-1行,第i行采用第j(一个十进制的数)种状态时,得到的方案可行的总数  
void dfs(int i,int j,int state,int nex)    //这里i代表列数,j代表当前位数(也可以说是行数-1,初始时为0),state代表状态数,nex代表下一列出现的状态
{
    if (j==N)    //用if判断每种情况都尝试去做,而不用if...else判断
    {
        dp[i+1][nex]+=dp[i][state];
        return;
    }
    if (((1<<j)&state)>0)
        dfs(i,j+1,state,nex);    //如果这个位置已经被上一列所占用,直接跳过
    if (((1<<j)&state)==0)
        dfs(i,j+1,state,nex|(1<<j));       //如果这个位置是空的,尝试放一个左右覆盖1*2的木板
    if (j+1<N && ((1<<j)&state)==0 && ((1<<(j+1))&state)==0)
        dfs(i,j+2,state,nex);     //如果这个位置以及下一个位置都是空的,尝试放一个上下覆盖2*1的木板,而此时要跳过下一个木块
    return;
}
int main()
{
    while (cin>>N>>M)
    {
        memset(dp,0,sizeof(dp));
        dp[1][0]=1;    //初始化第一列状态为0的方法数等于1
        for (int i=1;i<=M;i++)    //外层for循环遍历每一列
        {
            for (int j=0;j<(1<<N);j++)    //内层for遍历每一个列的所有状态
                if (dp[i][j])    //只要dp[i][j]方法数不为空,就执行dfs方法
                {
                    dfs(i,0,j,0);
                }
        }
        cout<<dp[M+1][0]<<endl;    //最后dp[m+1][0]就是结果
    }
}

https://blog.csdn.net/harrypoirot/article/details/23163485

一个大佬讲的状压dp

原文地址:https://www.cnblogs.com/tianzeng/p/9127490.html

时间: 2024-11-03 18:10:02

二:状压dp的相关文章

ZOJ 3471 Most Powerful(状压DP)

Recently, researchers on Mars have discovered N powerful atoms. All of them are different. These atoms have some properties. When two of these atoms collide, one of them disappears and a lot of power is produced. Researchers know the way every two at

BZOJ 3446: [Usaco2014 Feb]Cow Decathlon( 状压dp )

水状压dp. dp(x, s) = max{ dp( x - 1, s - {h} ) } + 奖励(假如拿到的) (h∈s). 时间复杂度O(n * 2^n) ---------------------------------------------------------------------------------- #include<bits/stdc++.h> #define rep(i, n) for(int i = 0; i < n; ++i) #define clr(x

2014 Super Training #1 B Fix 状压DP

原题: HDU 3362 http://acm.hdu.edu.cn/showproblem.php?pid=3362 开始准备贪心搞,结果发现太难了,一直都没做出来.后来才知道要用状压DP. 题意:题目给出n(n <= 18)个点的二维坐标,并说明某些点是被固定了的,其余则没固定,要求添加一些边,使得还没被固定的点变成固定的,可见题目中的图形sample. 由于n很小,而且固定点的顺序没有限制,所以需要用状态压缩DP. 注意:1.当一个没固定的点和两个固定了的点连接后,该点就被(间接)固定了(

UVa 11825 (状压DP) Hackers&#39; Crackdown

这是我做状压DP的第一道题,状压里面都是用位运算来完成的,只要耐下心来弄明白每次位运算的含义,还是容易理解的. 题意: 有编号为0~n-1的n台服务器,每台都运行着n中服务,每台服务器还和若干台其他服务器相连.对于每台服务器,你可以选择停止该台以及与这台服务器相连的服务器的一项服务.如果一台服务器的所有服务都被停止,则这台服务器瘫痪.问最多能使多少台服务器瘫痪 转化为数学模型(题目是如何抽象成这种数学模型的也要好好想想): 把n个集合尽可能多的分成若干组,使得每组所有集合的并集为全集.这里集合P

【POJ 3254】 Corn Fields(状压DP)

[POJ 3254] Corn Fields(状压DP) Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10891   Accepted: 5705 Description Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parce

nefu1109 游戏争霸赛(状压dp)

题目链接:http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1109 //我们校赛的一个题,状压dp,还在的人用1表示,被淘汰的人用0表示.倒着循环即可. //比赛的时候我用的是二维dp数组表示状态,一直是WA的,搞不懂原因...Orz... 代码: #include<iostream> #include<cstdio> #include<algorithm> #include<cstrin

【弱校胡策】2016.4.14 (bzoj2164)最短路+状压DP+矩阵乘法+高斯消元+树链剖分+线段树+背包DP

cyyz&qhyz&lwyz&gryz弱校胡策 命题人:cyyz ws_fqk T3暴力写挫了 50+10+0滚粗辣! 奇妙的约会(appointment.cpp/c/pas) [问题描述] DQS和sxb在网上结识后成为了非常好的朋友,并且都有着惊人 的OI水平.在NOI2333的比赛中,两人均拿到了金牌,并保送进入 HU/PKU.于是两人决定在这喜大普奔的时刻进行面基. NOI2333参赛选手众多,所以安排了n个考点,DQS在1号考点, 而sxb在n号考点.由于是举办全国性赛事

HDU 5135 Little Zu Chongzhi&#39;s Triangles(状压dp或者贪心)

题目大意:给你n个线段让你任意组成三角形,求组出来的三角形的面积的和最大为多少. 解题思路:首先你得知道海伦公式:S = sqrt(p*(p-a)*(p-b)*(p-c)), p = (a+b+c)/2. 思路一:贪心,按照边的长度进行排序,从大到小判断如果可以构成三角形,就让他构成三角形,这样组成的三角形的面积和一定是最大的. 思路二:状压dp,先暴力求出来所有可以组成的三角形对应的状态和面积,然后dp求解,状态转移公式是:dp[i|(f[j].xnum)] = max(dp[i|(f[j].

hdu 2167 方格取数 【状压dp】(经典)

<题目链接> 题目大意: 给出一些数字组成的n*n阶矩阵,这些数字都在[10,99]内,并且这个矩阵的  3<=n<=15,从这个矩阵中随机取出一些数字,在取完某个数字后,该数字周围8个点都不能取,问:取得数字的最大和为多少? 解题分析: 由于对每一个数,有选和不选两种可能,分别对应状态压缩中的1和0,且 n<=15,1<<15不是非常大,因此就可以非常自然的想到状态压缩. 此题要与普通的状压dp不同的是,当某一行取某种方案时,如何求出这种取数的所有取得的数之和,