论文:《周伟ftfish --- 动态规划之状态压缩》 关键之处在于: ①针对棋盘不同限制用dfs把每行可行的状态压缩表示成一个数存到s[]。 ②枚举当前处理行和上一行的状态时根据题目限制判断状态是否互斥。 ③有时棋盘上会有些点不能放置,我们也把一行中不能放置的点压缩成一个数存到no[]中,比如用00011000表示第3列和第4列不能放置。然后处理当前行时如果s[j1] & no[i] == 0表示当前放置情况与不能放置的点不冲突。   sgu 223 Little Kings  棋盘限制:在n*n(n<=10)的棋盘上放k个国王(可攻击相邻的8个格子,不能放其他国王),求方案数。 分析:当前行的状态矛盾只涉及到上一行,并且还有放几个国王的限制,所以设dp[i][j][k]表示处理到第i行,第i行状态为j放了k个国王的方案数 dp[i][j][k] = dp[i-1][j'][k-c[j']].


//sgu 223 状态压缩DP 棋盘
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MID(x,y) ((x+y)>>1)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;typedef long long LL;
const int sup = 0x7fffffff;
const int inf = -0x7fffffff;int n, k;
const int NUM_OF_PLACEMENGT = 520;
int s[NUM_OF_PLACEMENGT], c[NUM_OF_PLACEMENGT], place_num;         //the placement of each line
long long dp[13][NUM_OF_PLACEMENGT][103];void dfs(int p, int condition_num, int condition_one_amount){             //Store the placement of each lineif (p == n){s[++ place_num] = condition_num;//cout << place_num << " " << s[place_num] << endl;c[place_num] = condition_one_amount;return ;}dfs(p+1, condition_num << 1, condition_one_amount);if (!(condition_num & 1))dfs(p+1, condition_num << 1 | 1, condition_one_amount + 1);return ;
}
bool ifok(int s1, int s2){      //decide whether tha current condition and the last condition are comtradictry.if(s1 & s2) return false;         //和正上方判断if(s1 & (s2<<1))return false;     //和右上方判断if(s1 & (s2>>1))return false;     //和左上方判断return true;
}
int main(){while(scanf("%d %d", &n, &k) != EOF){//cout << n << " " << k << endl;mem(dp, 0);place_num = 0;dp[0][1][0] = 1;dfs(0, 0, 0);for (int i = 1; i <= n; i ++){for (int j1 = 1; j1 <= place_num; j1 ++){for (int j2 = 1; j2 <= place_num; j2 ++){for (int w = 0; w <= k; w ++){if (ifok(s[j1], s[j2]) && w-c[j1] >= 0)dp[i][j1][w] += dp[i-1][j2][w-c[j1]];}}}}long long res = 0;for (int j = 1; j <= place_num; j ++)res += dp[n][j][k];printf("%I64d\n", res);}return 0;
}

hdu 4539 郑厂长系列故事——排兵布阵 棋盘限制:在n*m(n<=100, m<=10)的棋盘上放士兵,每个士兵的曼哈顿距离2的地方都不能放别的士兵。并且有些地方不能放士兵。求最多能放几个士兵。 分析:因为距离为2可能涉及到上2行的状态,所以设dp[i][j1][j2]表示处理到第i行,第i行状态为j1,第i-1行状态为j2最多能放几个士兵。然后因为某些地方不能放置,需要用到③的s[j1] & no[i]。dp[i][j1][j2] = max(dp[i][j1][j2], dp[i-1][j2][j3])


//HDU 4539 状态压缩DP 棋盘
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MID(x,y) ((x+y)>>1)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;typedef long long LL;
const int sup = 0x7fffffff;
const int inf = -0x7fffffff;int n, m;
const int NUM_OF_PLACEMENGT = 500;
int s[NUM_OF_PLACEMENGT], c[NUM_OF_PLACEMENGT], place_num;         //the placement of each line
int dp[2][NUM_OF_PLACEMENGT][NUM_OF_PLACEMENGT];
vector  dd[NUM_OF_PLACEMENGT];
int no[105];void dfs(int p, int condition_num, int condition_one_amount){             //Store the placement of each lineif (p == m){s[++ place_num] = condition_num;//cout << condition_num << endl;c[place_num] = condition_one_amount;return ;}dfs(p+1, condition_num << 1, condition_one_amount);if (!(condition_num & 2))dfs(p+1, condition_num << 1 | 1, condition_one_amount + 1);return ;
}
bool ifok(int s1, int s2){      //decide whether tha current condition and the last condition are comtradictry.//if(s1 & s3)     return false;         //和正上方判断if(s1 & (s2<<1))    return false;     //和右上方判断if(s1 & (s2>>1))    return false;     //和左上方判断return true;
}
int main(){while(scanf("%d %d", &n, &m) == 2){mem(no, 0);place_num = 0;mem(dp, -1);dp[0][1][1] = 0;dfs(0, 0, 0);for (int i = 1; i <= n; i ++)for (int j = 1; j <= m; j ++){int tmp;scanf("%d", &tmp);if (tmp == 0)   no[i] += (1 << (m-j));}for (int i = 1; i <= n; i ++)for (int j1 = 1; j1 <= place_num; j1 ++){if(s[j1] & no[i])   continue;for (int j3 = 1; j3 <= place_num; j3 ++){if (s[j1] & s[j3])  continue;for (int j2 = 1; j2 <= place_num; j2 ++){if (ifok(s[j1],s[j2]) && dp[(i-1)&1][j2][j3] != -1){dp[i&1][j1][j2] = max(dp[i&1][j1][j2], dp[(i-1)&1][j2][j3] + c[j1]);;}}}}int res = 0;for (int j1 = 1; j1 <= place_num; j1 ++)for (int j2 = 1; j2 <= place_num; j2 ++)res = max(res, dp[n&1][j1][j2]);printf("%d\n", res);}return 0;
}

poj 1185 炮兵阵地 棋盘限制:在n*m(n<=100, m<=10)的棋盘上放士兵,每个士兵上下左右2格子内都不能放别的士兵。并且有些地方不能放士兵。求最多能放几个士兵。 分析:和上一题基本一样,就是判断状态互斥时有区别。


//POJ 1185 炮兵阵地 状态压缩DP#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MID(x,y) ((x+y)>>1)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;typedef long long LL;
const int sup = 0x7fffffff;
const int inf = -0x7fffffff;int n, m;
int no[104];
int dp[104][300][300];
vector  s,c;
void dfs(int p, int condition_num, int condition_amount){if (p == m){s.push_back(condition_num);c.push_back(condition_amount);//cout << condition_num << endl;return;}dfs(p + 1, condition_num << 1, condition_amount);if ((condition_num & 3) == 0)dfs(p + 1, condition_num << 1 | 1, condition_amount + 1);return ;
}int main(){scanf("%d %d", &n, &m);mem(no, 0);for (int i = 1; i <= n; i ++)for (int j = 1; j <= m; j ++){char c_tmp;cin >> c_tmp;if (c_tmp == 'H')no[i] += (1 << (m - j));}mem(dp, -1);dp[0][0][0] = 0;dfs(0, 0, 0);for (int i = 1; i <= n; i++){for (int j1 = 0; j1 < (int)s.size(); j1 ++){if (s[j1] & no[i])          //不能在H处continue;for (int j2 = 0; j2 < (int)s.size(); j2 ++){if (s[j1] & s[j2])      //上面一格continue;for (int j3 = 0; j3 < (int)s.size(); j3 ++){if (s[j1] & s[j3])      //上面两格continue;if (dp[i-1][j2][j3] != -1){dp[i][j1][j2] = max(dp[i][j1][j2], dp[i-1][j2][j3] + c[j1]);}}}}}int res = 0;for (int j1 = 0; j1 < (int)s.size(); j1 ++){for (int j2 = 0; j2 < (int)s.size(); j2 ++){res = max(res, dp[n][j1][j2]);}}printf("%d\n", res);return 0;
}

转载于:https://www.cnblogs.com/AbandonZHANG/archive/2013/03/31/4114013.html

状态压缩DP-棋盘模型总结相关推荐

  1. 由NP完全问题引出动态规划——状态压缩DP

    " 所有部分都应当在非强制的情况下组合回一起.要记住,你重组的那部分原来就是你拆解的.因此,如果你不能让它们组合回来的话,那一定是有原因的.要想尽一切办法,除了用锤头." – IB ...

  2. 0x56. 动态规划 - 状态压缩DP(习题详解 × 7)

    目录 Problem A. 最短Hamilton路径 ProblemB. 蒙德里安的梦想 Problem C. Corn Fields Problem D. 小国王 Problem E. 炮兵阵地 P ...

  3. POJ 2411 Mondriaan‘s Dream(最清楚好懂的状压DP讲解)(连通性状态压缩DP)

    poj 2411 Mondriaan's Dream(最清晰的状压DP解析) 闫氏DP大法好 我们这里是一列一列地来,因为是一个棋盘性的状态压缩DP,从哪个方向都一样 摆放的小方格总方案数 等价于 横 ...

  4. 状态压缩DP AcWing算法提高课 (详解)

    基础课的状态压缩点这里 基础课中 蒙德里安的梦想 属于 棋盘式状态压缩dp,最短Hamilton路径 属于 集合状态压缩dp 1064. 小国王(棋盘式/基于连通性) 这种棋盘放置类问题,在没有事先知 ...

  5. [转]状态压缩dp(状压dp)

    状态压缩动态规划(简称状压dp)是另一类非常典型的动态规划,通常使用在NP问题的小规模求解中,虽然是指数级别的复杂度,但速度比搜索快,其思想非常值得借鉴. 为了更好的理解状压dp,首先介绍位运算相关的 ...

  6. 第一章 动态规划 状态压缩DP

    1.基本概述 状态压缩dp和状态机一样,都是一种特殊的状态表示方式.状态机用一系列小状态表示某一状态.状态压缩dp用二进制数进行表示.虽然看代码起来时间复杂度比较高,但是很多的情况都给剪枝掉了. 状态 ...

  7. 动态规划-状态压缩DP

    [SCOI2005] 互不侵犯 题目描述 https://www.luogu.com.cn/problem/P1896 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它 ...

  8. 【AcWing】数位统计DP、树形DP、状态压缩DP、记忆化搜索

    [AcWing]数位统计DP.树形DP.状态压缩DP.记忆化搜索 一.数位统计DP 二.状态压缩DP 三.树形DP 四.记忆化搜索 一.数位统计DP 计数问题 给定两个整数 a 和 b,求 a 和 b ...

  9. 动态规划(5)状态压缩dp

    一.概述 动态规划的过程是随着阶段不断增长,在每个状态维度上不断扩展.在任意时刻,已经求出最优解的状态与尚未求出最优解的状态在各维度上的分界点组成了dp扩展的轮廓,对于某些问题,我们需要在动态规划的状 ...

  10. BZOJ1688|二进制枚举子集| 状态压缩DP

    Disease Manangement 疾病管理 Description Alas! A set of D (1 <= D <= 15) diseases (numbered 1..D) ...

最新文章

  1. thinkphp的select和find的区别(转)
  2. 李洋疯狂C语言之合法帧
  3. 开菜鸟驿站需要什么条件?投入成本大概要多少?
  4. javaScript中this以及window对象和window对象的name属性
  5. 视频图像的I帧、P帧、B帧详解
  6. 产品驱动程序一览表(ThinkPad X61)
  7. GBase 8c 安全特性
  8. matlab 蜗杆轮廓,solidworks环面蜗杆画法
  9. fatal: detected dubious ownership in repository git报错解决
  10. AWS SES发QQ邮箱拒收解决方案
  11. iOS工程师Mac上的必备软件
  12. 安全合规/GDPR--23--研究:GDPR风险评估与组织架构保障
  13. 灵遁者诗歌集《很白很白的云》序言内容
  14. 2021年印度经济发展研究报告
  15. 试题 算法训练 九宫格的奥(解题思路与代码)
  16. mysql 本日、本周、本月、本年 统计
  17. 【SOD论文阅读笔记】Visual Saliency Transformer
  18. pc屏幕与手机屏幕互相分享(幕享)
  19. APP测试反编译工具使用
  20. 图像处理:距离变换distance transform

热门文章

  1. 【NAACL2021】初探无监督的多跳问答对
  2. 教育部建议采纳:给予导师决定硕博士能否毕业的自主权!
  3. 基于DEAP库的python进化算法-7.多目标遗传算法NSGA-II
  4. python查看大文件的最后一行
  5. Kubernetes入门——从零搭建k8s集群
  6. 看懂这个故事,轻松实现从技术到管理的华丽转身!
  7. 网站运营之比较和差异化
  8. 35线性映射02—— 线性映射概念与运算、矩阵表示
  9. linux:文件及目录管理
  10. 【论文阅读】Deep Modular Co-Attention Networks for Visual Question Answering