http://poj.org/problem?id=3254
https://www.luogu.org/problemnew/show/P1896

把这两题放在一起,解题思路差不多。以POJ的为例

题意:给出 n ∗ m n*m n∗m的 01 01 01矩阵, 1 1 1表示能放数字, 0 0 0表示不能放数字,每个数字不能相邻,问方案数。

题解:状压DP模板题。

预处理出每一行的状态,压缩成十进制数。
d p [ i ] [ j ] 表 示 第 i 行 的 状 态 为 j 时 的 方 案 数 dp[i][j]表示第i行的状态为j时的方案数 dp[i][j]表示第i行的状态为j时的方案数
转移方程:
d p [ i ] [ j ] = d p [ i ] [ j ] + d p [ i − 1 ] [ k ] dp[i][j] = dp[i][j] + dp[i-1][k] dp[i][j]=dp[i][j]+dp[i−1][k] 只与前一行有关。
最后将所有的 d p [ n ] [ i ] dp[n][i] dp[n][i]累加即可

这题是没有要求放置个数的。

如果要求放置个数m
d p [ i ] [ j ] [ k ] 表 示 第 i 行 的 状 态 为 j 时 , 放 了 k 个 的 方 案 数 dp[i][j][k]表示第i行的状态为j时,放了k个的方案数 dp[i][j][k]表示第i行的状态为j时,放了k个的方案数
转移方程:
d p [ i ] [ j ] [ k ] = d p [ i ] [ j ] [ k ] + d p [ i − 1 ] [ k ] [ h − w [ j ] ] , w [ j ] 表 示 当 前 行 状 态 为 j 时 , 1 的 个 数 dp[i][j][k] = dp[i][j][k] + dp[i-1][k][h-w[j]],w[j]表示当前行状态为j时,1的个数 dp[i][j][k]=dp[i][j][k]+dp[i−1][k][h−w[j]],w[j]表示当前行状态为j时,1的个数
不要求个数

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#include<vector>
using namespace std;
#define inf 0x3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define mem(a,b) memset(a,b,sizeof(a));
#define lowbit(x)  x&-x;
#define debugint(name,x) printf("%s: %d\n",name,x);
#define debugstring(name,x) printf("%s: %s\n",name,x);
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-6;
const int maxn = 1e5+5;
const int mod = 1e8;
inline int read()
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}
int n,m;
int a[25][25],st[505],w[505];
int f[25];
ll dp[505][505];
int cal(int x){int res = 0;while(x){if(x&1) res++;x >>= 1;}return res;
}
int main() {scanf("%d%d",&n,&m);for(int i = 1; i <= n; i++){for(int j = 1; j <= m; j++){scanf("%d",&a[i][j]);}}for(int i = 1; i <= n; i++){int tmp = 0;for(int j = 1; j <= m; j++){tmp = (tmp<<1) + (a[i][j]==1?0:1);}f[i] = tmp;}int sz = 1<<m;int tot = 0;for(int i = 0; i < sz; i++){if(i&(i<<1)) continue;st[++tot] = i; //合法状态w[tot] = cal(i); //合法状态 1 的个数//dp[1][tot] = 1;}for(int i = 1; i <= tot; i++){if(st[i]&f[1]) continue;dp[1][i] = 1;}for(int i = 2; i <= n; i++){for(int j = 1; j <= tot; j++){if(st[j]&f[i]) continue;for(int k = 1; k <= tot; k++){if(st[k]&f[i-1]) continue;if(st[k]&st[j]) continue;dp[i][j] = (dp[i][j] + dp[i-1][k])%mod;}}}ll ans = 0;for(int i = 1; i <= tot; i++){ans += dp[n][i];ans %= mod;}printf("%lld\n",ans);
}

要求放置个数

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#include<vector>
using namespace std;
#define inf 0x3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define mem(a,b) memset(a,b,sizeof(a));
#define lowbit(x)  x&-x;
#define debugint(name,x) printf("%s: %d\n",name,x);
#define debugstring(name,x) printf("%s: %s\n",name,x);
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-6;
const int maxn = 1e5+5;
const int mod = 1e9+7;
inline int read()
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}
int n,m;
int w[105],st[105];
ll dp[105][105][105];  //第i行 第j种状态 用了k的棋子的方案数int cal(int x){int res = 0;while(x){if(x&1) res++;x >>= 1;}return res;
}
int main() {scanf("%d%d",&n,&m);int sz = 1<<n;int tot = 0;for(int i = 0; i < sz; i++){if(i&(i<<1)) continue;st[++tot] = i;w[tot] = cal(i);dp[1][tot][w[tot]] = 1;}for(int i = 2; i <= n; i++){for(int j = 1; j <= tot; j++){for(int k = 1; k <= tot; k++){if(st[j]&st[k]) continue;if(st[j]<<1&st[k]) continue;if(st[j]&st[k]<<1) continue;for(int h = w[j]; h <= m; h++){dp[i][j][h] += dp[i-1][k][h-w[j]];}}}}ll ans = 0;for(int i = 1; i <= tot; i++)ans += dp[n][i][m];printf("%lld\n",ans);
}

poj3254/洛谷P1896 状压dp相关推荐

  1. 洛谷P1896 互不侵犯【状压DP】

    题目链接:P1896 互不侵犯 分析:普通的状压DP再多加一维记个数,然后找到能转移到当前的状态更新答案: #include<bits/stdc++.h> using namespace ...

  2. 【洛谷 P1896】[SCOI2005]互不侵犯(状压dp)

    题目链接 题意:在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 这是道状压\(DP\)好题啊.. ...

  3. [状压dp]洛谷 P2157 学校食堂

    题目描述 小F 的学校在城市的一个偏僻角落,所有学生都只好在学校吃饭.学校有一个食堂,虽然简陋,但食堂大厨总能做出让同学们满意的菜肴.当然,不同的人口味也不一定相同,但每个人的口味都可以用一个非负整数 ...

  4. [状压dp] 洛谷 P1879 玉米田

    题目描述 Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ...

  5. 洛谷P2704 [NOI2001]炮兵阵地(状压dp)

    题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P&quo ...

  6. 【Luogu】P1896互不侵犯King(状压DP)

    题目链接 真是可恶,被数据范围坑了一把.想要一遍AC的希望破灭了-- 以后大家在做状压DP的时候一定要开long long-- 设f[i][j][k]表示考虑前i行,总共放了j个King,第i行状态为 ...

  7. POJ3254 状压DP模板

    Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 6321   Accepted: 3361 Descr ...

  8. 动态规划 —— 状压 DP

    [概述] 通常将以一个集合内的元素信息作为状态且状态总数为指数级别的动态规划称为状态压缩动态规划. 其是一类以集合信息为状态的特殊的动态规划问题,主要有传统集合动态规划与基于连通性状态压缩的动态规划两 ...

  9. 刷题周记(九)——#状压DP:最短Hamilton路径、小国王(互不侵犯)、玉米田(Corn Fields G)、愤怒的小鸟、吃奶酪、炮兵阵地、宝藏 #区间DP:清空字符串#DP:关灯问题II

    文章目录 --2020年12月20日(周日)------------------ 状压DP 一.最短Hamilton路径(模板题) 二.玉米田(P1879 [USACO06NOV]Corn Field ...

最新文章

  1. 瀑布式开发与敏捷开发的区别是什么
  2. 视觉语言研究进展到哪了?CVPR2021视觉语言研究全面概述,附430页ppt
  3. python输出文本-Python基础练习,查询文本内容并输出;
  4. 20150720 Two heads are better than one
  5. 【InfoQ大咖说直播回放】老司机聊程序员的职场道路选择
  6. Module.h 网狐的“com”工具箱
  7. 信用卡套现只要正常还款,银行是不是睁只眼闭只眼?
  8. Natasha 4.0 探索之路系列(二) 「域」与插件
  9. 让IE6、IE7、IE8支持CSS3
  10. 关于同时可用git命令clone和TortoiseGit拉取代码不需要密码
  11. 流媒体技术的国内外动态
  12. vue项目原理分析-1:组件间传值
  13. Mapx 具体使用方法
  14. 古代汉语(王力版)笔记 通论8-9
  15. 高手攻关考试心得:RHCE实战详细经验
  16. python第一次考试_python 全栈开发,Day16(函数第一次考试)
  17. Tungsten Fabric知识库丨关于OpenStack、K8s、CentOS安装问题的补充
  18. 迪杰斯特拉算法及变式(最短距离,打印路径,最短经过节点数)
  19. word饼图如何画引导线_#excel表格饼状图制作#如何在饼形图中添加引导线(Excel)...
  20. 《卸甲笔记》-单行函数对比之二

热门文章

  1. R语言实现简单的网页数据抓取
  2. 学习心得:HSV颜色空间
  3. 如何对复杂网络建模所需要的数据进行预处理
  4. 前端优化-前端性能优化
  5. Hadoop入门——初识Hadoop 自学hadoop视频教程
  6. 简述MACD指标以及它的组成MACD、MACDsignal和MACDhist
  7. javascript contains方法
  8. 思科EtherChannel链路聚合
  9. 按键判断之GetKeyState 和 GetAsyncKeyState 区别
  10. iCheck组件使用方法总结