Hdu 4539 【状态DP】.cpp
题意:
一个炮兵可以攻打和他之间曼哈顿距离为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的更多相关文章
- hdu 4539(状态压缩dp)
题意:曼哈顿距离是指:|x1-x2|+|y1-y2|,只要知道这个概念题意就懂了. 分析:这道题与前面做的几道题有所不同,因为当前行不仅与前一行有关,而且与前两行有关,所以我们开数组的时候还要记录前两 ...
- HDU 4539郑厂长系列故事――排兵布阵(状压DP)
HDU 4539 郑厂长系列故事――排兵布阵 基础的状压DP,首先记录先每一行可取的所哟状态(一行里互不冲突的大概160个状态), 直接套了一个4重循环居然没超时我就呵呵了 //#pragma co ...
- hdu 4614 pieces 状态DP
题意:给你一个长度小于等于16的字符串,每次可以删除一个回文传,问你最少删除干净的字数. 状态+dp dp[i] = min(dp[i],dp[j]+dp[j^i]);(j是i的字串): 连接:htt ...
- hdu 4778 Gems Fight! 博弈+状态dp+搜索
作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4102743.html 题目链接:hdu 4778 Gems Fight! 博弈+状态dp+搜 ...
- 【状态DP】 HDU 1074 Doing Homework
原题直通车:HDU 1074 Doing Homework 题意:有n门功课需要完成,每一门功课都有时间期限t.完成需要的时间d,如果完成的时间走出时间限制,就会被减 (d-t)个学分.问:按怎样 ...
- hdu 4352 数位dp + 状态压缩
XHXJ's LIS Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- hdu 5135(2014广州—状态dp)
t题意:给你n条边,构造任意个三角形,一个三角形恰好只用3条边,每条边只能一次,求面积最大值 思路: 最开始想的是先排序从大到小取,但感觉并不怎么靠谱. 最多12条边,所以可以求出所有可能的三角形面积 ...
- Hdu 3001 Travelling 状态DP
题目大意 一次旅游,经过所有城市至少一次,并且任何一座城市访问的次数不能超过两次,求最小费用 每个城市最多访问两次,用状态0,1,2标识访问次数 把城市1~N的状态按照次序连接在一起,就组成了一个三进 ...
- HDU 2829 区间DP & 前缀和优化 & 四边形不等式优化
HDU 2829 区间DP & 前缀和优化 & 四边形不等式优化 n个节点n-1条线性边,炸掉M条边也就是分为m+1个区间 问你各个区间的总策略值最少的炸法 就题目本身而言,中规中矩的 ...
随机推荐
- 移动端 前端框架 amaze ui
移动端 前端框架 amaze ui http://amazeui.org/?_ver=2.x
- UVA 10718 Bit Mask 贪心+位运算
题意:给出一个数N,下限L上限U,在[L,U]里面找一个整数,使得N|M最大,且让M最小. 很明显用贪心,用位运算搞了半天,样例过了后还是WA,没考虑清楚... 然后网上翻到了一个人家位运算一句话解决 ...
- smartforms客制页格式
smartforms需要打印非A4纸时需要手动创建页格式:创建事务代码:spad, 操作的时候需要 把所有步骤都做一遍方可正常打印,不然只能停留在预览界面无法打印.
- PP屏幕增强点
生产订单CO01/CO02/CO03屏幕增强 smod:PPCO0012 工票输入CO11N SMOD:CONFPP07 增强里经常会用内存读取数据:比如: ) TYPE c. FIELD-SYMBO ...
- 轻应用 lapp
轻应用 LAPP (Light App) 即轻应用是一种无需下载.即搜即用的全功能 App,既有媲美甚至超越native app的用户体验,又具备webapp的可被检索与智能分发的特性,将有效解决优质 ...
- Android broadcast
发送广播而且接受.发送两个广播 Intent intent = new Intent(); intent.setAction("com.wxq.CUSTOM_INTENT"); s ...
- java.util.Queue用法
队列是一种特殊的线性表,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作.进行插入操作的端称为队尾,进行删除操作的端称为队头.队列中没有元素时,称为空队列. 在队列这 ...
- 3xian退役贴【深思。】
这是原文: 最后一天,漫天飘起了雪花,假装欢送我离去. 这次WF之战不太顺利,早期的C题大概花了1秒钟构思,然而由于输出格式多了一个空格直到两个半小时才逃脱Wrong Answer的纠缠.还好lynn ...
- SVN的项目管理
基于SVN的项目管理——集中与分散 我们在此处不讨论 GIT 比 SVN 好多少,也不讨论 Maven 和 Gradle 哪个好用,基于现有的开发环境,大多数公司还是采用 SVN + Maven ...
- 第二章排错的工具:调试器Windbg(上)
感谢博主 http://book.51cto.com/art/200711/59731.htm <Windows用户态程序高效排错>第二章主要介绍用户态调试相关的知识和工具.本文主要讲了排 ...