题意:

  一个炮兵可以攻打和他之间曼哈顿距离为2的士兵,给出你一块n*m的战场,告诉你哪些地方可以站人哪些地方不可以,问你最多可以安放多少个士兵?

  n <= 100, m <= 10

思路:

  这道题暴力是不可以的,因为状态太多了

  可以状态DP来做,用一个数组G记录战场的限制,然后用一个数组dp[当前状态或者是前一个状态][当前状态的十进制表示][前一个状态的十进制表示]

  因为用的是G[1<<m]来表示,所以时间复杂度是n*(2^m)*(2^m)*(2^m),m最多为10,所以时间复杂度就是10*1024*1024*1024,显然这样的时间复杂度也是说不过去的。所以就用一个预处理,预处理出满足基本条件的状态,即水平距离上曼哈顿距离不为2的状态,我用bir[][2]来存预处理出来的基本状态,bir[][0]表示的是预处理的符合基本条件状态的二进制数,bir[][1]表示的是这个状态中1的个数

  

Tips:

  因为用的是滚动数组,所以应该注意n == 1的情况

  位运算的优先级比 != 高,所以当我判断是否符合条件的时候应该直接写if(***)或者是if((***) != 0)

  不能写 == 1,因为不管是哪种位运算,出来的结果都不一定是1,只能是 != 0

  这里还有一个处理状态sta里面有多少个1的有效办法就是用lowbit(x) { return (x)&(-x)}, lowbit(x)可以提取x的最后一个1至最后一个0,这个可以利用补码原理来理解

  这样不断 i -= lowbit(i), bir[][1]++, 就可以得到相对应1的个数了

Code:

 #include <stdio.h>
#include <cstring>
#include <bitset>
#include <iostream>
#include <algorithm>
using namespace std; int n, m;
int G[], bir[<<|][], top;
int dp[][<<|][<<|];
int ans; int lowbit(int x)
{
return (x)&(-x);
} void init()
{
top = ;
int st = <<;
for (int i = ; i < st; ++i) {
if (((i>>)&i) || ((i<<)&i)) continue;
int tmp = i;
bir[top][] = i;
while (tmp) {
tmp -= lowbit(tmp);
bir[top][]++;
}
top++;
}
} void DP()
{
int st = <<m;
for (int i = ; i < top && bir[i][] < st; ++i)
if ((bir[i][]&(G[]^(st-))) != ) continue; /// == 1!!!!!
else ans = max(ans, bir[i][]); if (n == ) return; for (int i = ; i < top && bir[i][] < st; ++i) {
for (int j = ; j < top && bir[j][] < st; ++j) {
if ( (bir[i][]&(G[]^(st-))) !=
||(bir[j][]&(G[]^(st-))) !=
||((bir[i][]<<)&bir[j][]) || ((bir[i][]>>)&bir[j][])) continue;
dp[][j][i] = bir[i][]+bir[j][];
ans = max(ans, dp[][j][i]);
}
}
// printf("___2___%d\n", ans);
int t = ;
for (int i = ; i < n; ++i) {
for (int j = ; j < top && bir[j][] < st; ++j) {
if (bir[j][]&(G[i-]^(st-))) continue;
for (int k = ; k < top && bir[k][] < st; ++k) {
if (bir[k][]&(G[i-]^(st-))) continue;
for (int l = ; l < top && bir[l][] < st; ++l) {
if ( ((G[i]^(st-))&bir[l][])
||(bir[l][]&bir[j][])
||((bir[l][]<<)&bir[k][])
||((bir[l][]>>)&bir[k][])) continue;
dp[t][l][k] = max(dp[t][l][k], dp[(t+)%][k][j]+bir[l][]);
ans = max(ans, dp[t][l][k]);
}
}
}
t = (t+)%;
}
} int main()
{
// freopen("in.txt", "r", stdin);
init(); while (~scanf("%d %d", &n, &m)) {
ans = -;
memset(dp, , sizeof(dp));
for (int i = ; i < n; ++i) {
int p = , tmp;
for (int j = ; j < m; ++j) {
scanf("%d", &tmp);
if(tmp != ) p |= (<<j); ///!!!!
}
G[i] = p;
}
DP();
printf("%d\n", ans);
}
return ;
}

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4539

Hdu 4539 【状态DP】.cpp的更多相关文章

  1. hdu 4539(状态压缩dp)

    题意:曼哈顿距离是指:|x1-x2|+|y1-y2|,只要知道这个概念题意就懂了. 分析:这道题与前面做的几道题有所不同,因为当前行不仅与前一行有关,而且与前两行有关,所以我们开数组的时候还要记录前两 ...

  2. HDU 4539郑厂长系列故事――排兵布阵(状压DP)

    HDU 4539  郑厂长系列故事――排兵布阵 基础的状压DP,首先记录先每一行可取的所哟状态(一行里互不冲突的大概160个状态), 直接套了一个4重循环居然没超时我就呵呵了 //#pragma co ...

  3. hdu 4614 pieces 状态DP

    题意:给你一个长度小于等于16的字符串,每次可以删除一个回文传,问你最少删除干净的字数. 状态+dp dp[i] = min(dp[i],dp[j]+dp[j^i]);(j是i的字串): 连接:htt ...

  4. hdu 4778 Gems Fight! 博弈+状态dp+搜索

    作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4102743.html 题目链接:hdu 4778 Gems Fight! 博弈+状态dp+搜 ...

  5. 【状态DP】 HDU 1074 Doing Homework

    原题直通车:HDU  1074  Doing Homework 题意:有n门功课需要完成,每一门功课都有时间期限t.完成需要的时间d,如果完成的时间走出时间限制,就会被减 (d-t)个学分.问:按怎样 ...

  6. hdu 4352 数位dp + 状态压缩

    XHXJ's LIS Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  7. hdu 5135(2014广州—状态dp)

    t题意:给你n条边,构造任意个三角形,一个三角形恰好只用3条边,每条边只能一次,求面积最大值 思路: 最开始想的是先排序从大到小取,但感觉并不怎么靠谱. 最多12条边,所以可以求出所有可能的三角形面积 ...

  8. Hdu 3001 Travelling 状态DP

    题目大意 一次旅游,经过所有城市至少一次,并且任何一座城市访问的次数不能超过两次,求最小费用 每个城市最多访问两次,用状态0,1,2标识访问次数 把城市1~N的状态按照次序连接在一起,就组成了一个三进 ...

  9. HDU 2829 区间DP & 前缀和优化 & 四边形不等式优化

    HDU 2829 区间DP & 前缀和优化 & 四边形不等式优化 n个节点n-1条线性边,炸掉M条边也就是分为m+1个区间 问你各个区间的总策略值最少的炸法 就题目本身而言,中规中矩的 ...

随机推荐

  1. Codility上的问题 (17) PI 2012

    这个题比较简单,给定一个整数数组,对每个元素,求出和它最近比它大的数的距离(下标绝对值),如果没有比它大的数,认为距离是0. 数组元素个数 N [0..50000],数组元素范围[-10^9, +10 ...

  2. HDU 3068 最长回文 Manacher算法

    Manacher算法是个解决Palindrome问题的O(n)算法,能够说是个超级算法了,秒杀其它一切Palindrome解决方式,包含复杂的后缀数组. 网上非常多解释,最好的解析文章当然是Leetc ...

  3. 微软HR泄露的asp.net面试题

    1.面向对象的思想主要包括什么? 2.什么是ASP.net中的用户控件? 3.什么叫应用程序域?什么是受管制的代码?什么是强类型系统?什么是装箱和拆箱?什么是重载? 4.列举一下你所了解的XML技术及 ...

  4. 转换函数CONVERSION_EXIT_TSTRN_OUTPUT

    CONVERSION_EXIT_TSTRN_OUTPUT 在路线表TVRO中字段TDVZND 运输提前时间,取出来的数值没有转换,需要此函数进行转换.如14400,000  转换后为14,400:00 ...

  5. 好多NFS的文章

    http://www.cnblogs.com/lidabo/category/587288.html http://www.cnblogs.com/lidabo/p/4380555.html

  6. CImageList类Create函数参数解析

    前面提到了CImageList类的Create(...)函数,虽然MSDN上已经有所解释,但仍有网友问到参数的具体含义,下面就我的理解,对参数进行一次轻量级的剖析 函数原型(其他重载函数请参看msdn ...

  7. ios23- 文件下载(同步和异步)

    1.第一步:创建一个单例视图 #import <UIKit/UIKit.h> @interface ios23_downViewController : UIViewController& ...

  8. 用XCA(X Certificate and key management)可视化程序管理SSL 证书(3)--创建自己定义的凭证管理中心(Certificate Authority)

    在第"用XCA(X Certificate and key management)可视化程序管理SSL 证书(2)---创建证书请求"章节中,我们介绍了怎样用XCA创建SSL证书请 ...

  9. 我在知乎上关于Laser200/310电脑的文章。

    我是30年前从Laser-310起步的,我来回答这个问题. 主要硬件规格: CPU:Z-80A/4.7MHz主频 16K RAM + 2K Video RAM 16K ROM 磁带输出:波特率300 ...

  10. hdu 4455 Substrings (DP 预处理思路)

    Substrings Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...