暑假集训Day2 状压dp 特殊方格棋盘
首先声明 : 这是个很easy的题 可这和我会做有什么关系
题目大意:
   在n*n的方格棋盘上放置n个车,某些格子不能放,求使它们不能互相攻击的方案总数。
   注意:同一行或同一列只能有一个车,否则会相互攻击、
输入:
   输入文件第一行,有两个数n, m ,n表示方格棋盘大小,m表示不能放的格子数量
   下面有m行,每行两个整数,为不能放的格子的位置。
算法分析:
  1. 显然这是个状压dp(好吧没有那么显然,但是是状压dp就完了)  状态很多而且给出的数据范围很小(这个题给出的20>=n)
  2. 我们定义一个数组f[i],表示第 i 个状态所满足的方案数
        举个栗子: 1011 就可以表示当前行的状态为第二列还可以放车,而第一三四行已经在之前的状态中放车了(~~一列只能有一个车这不是显然吗~~)
    3. 题中给出一个限制 , 即有m个位置是不能放车的 , 我们用a数组存储该位置
     **这个地方就要按着状压dp自己的方式存储了**
        再举个栗子: 如果第二行第三列有个障碍物 那么我们将a[2] += 1<<(3-1)(这里将a数组初始化为0 想象一下一个二进制串在是0的时候 就是 000000  如果要在第三列的位置加上障碍物 可以想象到就是000100 也就是0 + 1<<(3-1))
  4. 在这个地方我们先提及一下lowbit数组 `int lowbit(int x){return x & -x;}`
 lowbit数组的目的是求出x的二进制表示中最小位的1的位置
       还是举个例子 101000 lowbit的结果就是1000
                    1100 lowbit的结果就是100
        具体实现可参见度娘
        lowbit数组具体用处我们已经了解了 那么lowbit数组有什么用呢?
        再来回想一下我们定义的f数组 当前i表示状态 如果我们用 for(int i=S;i;i-=lowbit(i))cnt++;这样的代码
        很轻松就可以求出当前状态中1的个数 , 也就是当前状态已经放了的车的个数,以及当前为第几行 ,显然个数 = cnt = 第几行(一个n*n的方格,放n个车,每一行有且仅有一个车)
  5.然后就可以进行动态转移方程了,具体方程如下
    这里的i即枚举的当前行的每一个可能放的车(我们只知道当前行一定会放一个车,但是车在哪里我们并不清楚,因此枚举一遍并累加满足条件的方案书)
    而a[cnt]则表示当前行的障碍物情况
    刚才我们已经提过lowbit(i)可以求出最右边的i的位置 我们外层的i每次减去一个i 即进行当前行下个车可能位置的求解
    注意一个小细节`a[cnt] & lowbit(i)`这里表示当前行障碍物并不与当前行的车位置冲突,可以在这里放车,即可以由上一行的状态转移过来
    s = S^lowbit(i) :S 异或 lowbit(i)即求出如果当前行车的位置在lowbit(i)那么上一行的状态就是s 然后累加到当前行的方案数即可
for(int i=S;i;i-=lowbit(i)){
            if(!(a[cnt] & lowbit(i))){
                int s=S^lowbit(i);
                f[S]+=f[s];
            }
        }
AC代码
#include<bits/stdc++.h>
const int maxn=(1<<20)-1;
typedef long long LL;
LL f[maxn],a[25];
int lowbit(int x){return x & -x;};
int main(){
    int n,m;scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i){
        int x,y;scanf("%d%d",&x,&y);
        a[x]+=1<<(y-1);
    }
    f[0]=1;
    int maxs=1<<n;
    for(int S=1;S<=maxs;++S){
        int cnt=0;
        for(int i=S;i;i-=lowbit(i))cnt++;
        for(int i=S;i;i-=lowbit(i)){
            if(!(a[cnt] & lowbit(i))){
                int s=S^lowbit(i);
                f[S]+=f[s];
            }
        }
    }
    printf("%lld\n",f[maxs-1]);
    return 0;
}
暑假集训Day2 状压dp 特殊方格棋盘的更多相关文章
- poj 3254 Corn Fields (状压dp)(棋盘dp)
		状压dp入门题 因为当前行的状态只和上一行有关 所以可以一行一行来做 因为m <= 12所以可以用二进制来表示放了或者没有放 0表示没放,1表示放 f[i][state]表示第i行状态为stat ... 
- [状压dp]HDOJ1565 方格取数(1)
		中文题~~ 题意略 $n\le 20$ ! 很明显是状压! #include <cstdio> #include <cstdlib> #include <cstring& ... 
- POJ 1185 炮兵阵地 (状压dp)(棋盘dp)
		这题和poj 3254很像,但是更复杂了一些 都属于棋盘里放东西,然后又各种各样的限制,然后求方案或者最大值 (1)上一道题距离要大于1,这道题是大于2.所以判断的时候变成 !(x & (x ... 
- 暑假集训Day2 互不侵犯(状压dp)
		这又是个状压dp (大型自闭现场) 题目大意: 在N*N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. ... 
- 暑假集训 || 状压DP
		emm 位操作实现技巧: 获得第i位的数据: if(!(data & (1<< i))) 则data的第 i 位为0,else 为 1 设置第i位为1,data=(data | ... 
- 暑假集训Day 4   P4163 [SCOI2007]排列 (状压dp)
		状压dp (看到s的长度不超过10就很容易想到是状压dp了 但是这个题的状态转移方程比较特殊) 题目大意 给一个数字串 s 和正整数 d, 统计 s 有多少种不同的排列能被 d 整除(可以有前导 0) ... 
- HDU 1565&1569 方格取数系列(状压DP或者最大流)
		方格取数(2) Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ... 
- HDU 1565 - 方格取数(1) - [状压DP][网络流 - 最大点权独立集和最小点权覆盖集]
		题目链接:https://cn.vjudge.net/problem/HDU-1565 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32 ... 
- 特殊方格棋盘【状压DP】
		特殊方格棋盘[状压DP] 讲真状压DP这个东西只不过是有那么亿丢丢考验心态罢了(确信) 先从板子题说起,另加一些基础知识 题目描述 在的方格棋盘上放置n 个车,某些格子不能放,求使它们不能互相攻击的方 ... 
随机推荐
- jQuery-语言基础整理
			jQuery是js的一个类库,主要封装的是js中DOM操作部分,使用和原生js一样 1.需要先引入页面才可以使用 代码引入:<script src='jquery.js'></scr ... 
- Rocket - util - Timer
			https://mp.weixin.qq.com/s/Z4JJhZ_jL1lqF1nf_orq9A 简单介绍Timer的实现.  1. 基本功能 实现定时器的功能. 2. Ti ... 
- xss(跨站脚本攻击)
			xss(跨站脚本攻击) 原理:攻击者可以通过在页面中注入恶意链接或者脚本代码,当受害者访问时,脚本代码会在其浏览器中执行,这个时候,我们可以获取当前用户的cookie或者进行重定向等操作. xss造成 ... 
- Java实现 LeetCode 779 第K个语法符号(递归)
			779. 第K个语法符号 在第一行我们写上一个 0.接下来的每一行,将前一行中的0替换为01,1替换为10. 给定行数 N 和序数 K,返回第 N 行中第 K个字符.(K从1开始) 例子: 输入: N ... 
- Java实现 LeetCode 749 隔离病毒(DFS嵌套)
			749. 隔离病毒 病毒扩散得很快,现在你的任务是尽可能地通过安装防火墙来隔离病毒. 假设世界由二维矩阵组成,0 表示该区域未感染病毒,而 1 表示该区域已感染病毒.可以在任意 2 个四方向相邻单元之 ... 
- Java实现 LeetCode 500 键盘行
			500. 键盘行 给定一个单词列表,只返回可以使用在键盘同一行的字母打印出来的单词.键盘如下图所示. 示例: 输入: ["Hello", "Alaska", & ... 
- Java实现 蓝桥杯 算法提高 队列操作
			算法提高 队列操作 时间限制:1.0s 内存限制:256.0MB 提交此题 问题描述 队列操作题.根据输入的操作命令,操作队列(1)入队.(2)出队并输出.(3)计算队中元素个数并输出. 输入格式 ... 
- Android中WebView如何加载JavaScript脚本
			主Activity和XML布局,末尾附上效果图 package com.example.myapplication; import androidx.appcompat.app.AppCompatAc ... 
- java实现趣味拼算式
			匪警请拨110,即使手机欠费也可拨通! 为了保障社会秩序,保护人民群众生命财产安全,警察叔叔需要与罪犯斗智斗勇,因而需要经常性地进行体力训练和智力训练! 某批警察叔叔正在进行智力训练: 1 2 3 4 ... 
- TZOJ Start
			描述 After the Online Round contest, we believe that you have already known how to write programs in A ... 
