POJ 1185(状态压缩DP)

和POJ 3254很像。连续两个都不一样需要添加移位两位的条件,dp数组中多了一维保存上上一行。递推公式也变成求最大值。

初始化的时候从dp[1][0][i]开始,0是根据st数组的起始。

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>

#define Max 1000001
#define MAXN 150000
#define MOD 100000000
#define rin freopen("in.txt","r",stdin)
#define rout freopen("1.out","w",stdout)
#define Del(a,b) memset(a,b,sizeof(a))
#define INF 1000000000
using namespace std;
typedef long long LL;
const int N = 105;
const int M = 70;
int st[M], map[N];
int dp[N][M][M];
int num[M];
char temp[N];
inline bool judge1(int x) {
    if (x & (x << 1))
        return 0;
    if (x & (x << 2))
        return 0;
    return 1;
}
bool judge2(int i, int x) {
    return (map[i] & st[x]);
}
int getnum(int i) {
    int ret = 0;
    while (i) {
        ret++;
        i &= i - 1;
    }
    return ret;
}
int main() {
    //rin;
    int n, m;
    while (scanf("%d%d", &n, &m) != EOF) {
        if (n == 0 && m == 0)
            break;
        Del(st, 0);
        Del(map, 0);
        Del(dp, -1);
        Del(num, 0);
        for (int i = 1; i <= n; i++) {
            scanf("%s", temp + 1);
            for (int j = 1; j <= m; j++) {
                if (temp[j] == ‘H‘)
                    map[i] += (1 << (j - 1));
            }
        }
        int cnt = 0;
        for (int i = 0; i < (1 << m); i++) {
            if (judge1(i)) {
                st[cnt] = i;
                cnt++;
            }
        }

        for (int i = 0; i < cnt; i++) {
            num[i] = getnum(st[i]);
            if (!judge2(1, i))
                dp[1][0][i] = num[i];
        }
        for (int i = 2; i <= n; i++) {
            for (int t = 0; t < cnt; t++) {
                if (judge2(i, t))
                    continue;
                for (int j = 0; j < cnt; j++) {
                    if (st[t] & st[j])
                        continue;
                    for (int k = 0; k < cnt; k++) {
                        if (st[t] & st[k])
                            continue;
                        if (dp[i - 1][j][k] == -1)
                            continue;
                        dp[i][k][t] = max(dp[i][k][t],
                                dp[i - 1][j][k] + num[t]);
                    }
                }
            }
        }

        int ans = 0;
        for (int i = 1; i <= n; i++)
            for (int j = 0; j < cnt; j++)
                for (int k = 0; k < cnt; k++)
                    ans = max(ans, dp[i][j][k]);
        printf("%d\n", ans);
    }
}
时间: 2024-10-12 04:11:23

POJ 1185(状态压缩DP)的相关文章

Mondriaan&#39;s Dream(POJ 2411状态压缩dp)

题意:用1*2的方格填充m*n的方格不能重叠,问有多少种填充方法 分析:dp[i][j]表示i行状态为j时的方案数,对于j,0表示该列竖放(影响下一行的该列),1表示横放成功(影响下一列)或上一列竖放成功.状态转移时,枚举每一行可能的状态上一行取反得下一行能放的状态. #include <map> #include <set> #include <list> #include <cmath> #include <queue> #include &

POJ 3311 状态压缩DP

题意:求从0点走到所有点又走回来的最短距离 该题又很多做法,我用的是弗洛伊德+状态压缩 先遍历所有点,求出两点间最短的距离,而后用状态压缩表示该点是否走过,(1<<n)-1则表示所有点都走过. 附AC代码 #include<stdio.h> #include<string.h> int map[12][12]; int dp[(1<<12)+1][12]; int min1(int a,int b) { if(a<b) return a; return

poj 3250 状态压缩dp入门

Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7798   Accepted: 4159 Description Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yumm

poj 1185 状态压缩

炮兵阵地 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 27926   Accepted: 10805 Description 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),如下图.在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队):一支炮兵部队在地图上的攻

poj 2688 状态压缩dp解tsp

题意: 裸的tsp. 分析: 用bfs求出任意两点之间的距离后可以暴搜也可以用next_permutation水,但效率肯定不如状压dp.dp[s][u]表示从0出发访问过s集合中的点,目前在点u走过的最短路程. 代码: //poj 2688 //sep9 #include <iostream> #include <queue> using namespace std; const int maxW=32; const int maxN=12; int dx[4]={-1,1,0,

POJ 1185(状态压缩原来还可以这样)

吐槽一下,刚做完两个状压的题,想着是一样的思路.没想到被坑了 有点类似于图论题目中不用邻接矩阵而用存储点将数据规模从输入范围->输入量 刚开始看题以为是攻击范围也不能重合,于是就是考虑到4次的范围.然后就是i-1,j-2两行如何组合而成. 果断TLE,如果用dp[maxn][1<<10][1<<10],MLE,TLE. 其实换个思路,10个方格的组合情况其实至多就只有60种,可以换成存储个数. 不吐槽了,贴一个代码.懒得自己写了. #include <iostream&

hdu1143 状态压缩dp 记忆化搜索写法

http://poj.org/problem?id=1143 Description Christine and Matt are playing an exciting game they just invented: the Number Game. The rules of this game are as follows. The players take turns choosing integers greater than 1. First, Christine chooses a

poj 1185 炮兵阵地(状态压缩dp)

Description 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),如下图.在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队):一支炮兵部队在地图上的攻击范围如图中黑色区域所示: 如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格.图上其它白色网格均攻击不

POJ 3254 Corn Fields 状态压缩DP (C++/Java)

http://poj.org/problem?id=3254 题目大意: 一个农民有n行m列的地方,每个格子用1代表可以种草地,而0不可以.放牛只能在有草地的,但是相邻的草地不能同时放牛, 问总共有多少种方法. 思路: 状态压缩的DP. 可以用二进制数字来表示放牧情况并判断该状态是否满足条件. 这题的限制条件有两个: 1.草地限制. 2.相邻限制. 对于草地限制,因为输入的时候1是可以种草地的. 以"11110"草地分析,就只有最后一个是不可以种草的.取反后得00001  .(为啥取反

poj 2411 Mondriaan&#39;s Dream(状态压缩+dp)

 题意:用1*2砖块铺满n*m的房间. 思路转自:http://www.cnblogs.com/scau20110726/archive/2013/03/14/2960448.html 因为这道题输入范围在11*11之间,所以可以先打表直接输出.......... 状态压缩DP 经典覆盖问题,输入n和m表示一个n*m的矩形,用1*2的方块进行覆盖,不能重叠,不能越出矩形边界,问完全覆盖完整个矩形有多少种不同的方案 其中n和m均为奇数的话,矩形面积就是奇数,可知是不可能完全覆盖的.接着我们来看