题意:

  一个炮兵可以攻打和他之间曼哈顿距离为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. URL vs. HTML 录制模式

    转自:http://blog.csdn.net/testing_is_believing/article/details/5274188 一般来说,如果是标准使用IE访问的B/S架构,应该使用HTML ...

  2. [每日一题] OCP1z0-047 :2013-08-29 NULL............................................................168

    转载请注明出处:http://blog.csdn.net/guoyjoe/article/details/10558305 正确答案:B 用函数可以针对各种数据类型时行操作,包括NULL值在内.其中有 ...

  3. 【翻译】ASP.NET Web API是什么?

    原文 [翻译]ASP.NET Web API是什么? 说明:随微软ASP.NET MVC 4一起发布的还有一个框架,叫做ASP.NET Web API.目前国内关注这项技术的人似乎还很少,这方面的文章 ...

  4. 【Demo 0004】Android 布局

    本章学习要点:        1.  了解Android 常见的四种布局结构;        2.  掌握四种布局及混合布局的使用方法:        3.  掌握布局中定义键值的意义以及参数使用方法 ...

  5. jquery mobile 对手势触控提供了如下几个事件监听:

    jquery mobile 对手势触控提供了如下几个事件监听: 复制代码代码如下: tap  当用户点屏幕时触发taphold 当用户点屏幕且保持触摸超过1秒时触发swipe 当页面被垂直或者水平拖动 ...

  6. 利用iframe技巧获取訪问者qq

    今天工作时,有个暂时加的好友问我,怎么利用web页面获取訪问者的qq. 曾经没有接触过,感觉到非常好奇,可是工作中脑子非常亢奋,转的快,利用所学的知识迅速想到一条技巧,那就是假想用户在进入我们设定的页 ...

  7. c++在string类源

    一:回想 (1)c++中的string类是在面试中和笔试中常常考的题目: project代码免费下载 string类的自行实现 (2)c++中的string类和fstream类合起来是处理外部数据的利 ...

  8. Nginx设置alias实现虚拟目录 alias与root的用法区别

    Nginx 貌似没有虚拟目录的说法,因为它本来就是完完全全根据目录来设计并工作的.如果非要给nginx安上一个虚拟目录的说法,那就只有alias标签比较"像",干脆来说说alias ...

  9. qt事件传递过程和处理

    处理监控系统的时候遇到问题,在MainWidget中创建多个子Widget的时候,原意是想鼠标点击先让MainWidget截获处理后再分派给子Widget去处理,但调试后发现如果子Widget重新实现 ...

  10. 细说UI线程和Windows消息队列

    在 Windows应用程序中,窗体是由一种称为“ UI线程( User Interface Thread)”的特殊类型的线程创建的. 首先, UI线程是一种“线程”,所以它具有一个线程应该具有的所有特 ...