poj1185 状态压缩经典题

状态压缩的好题,直接求会爆内存,先把所有可能的状态求出来存在stk里,然后f[i][k][t]表示i行状态为t,i-1状态为k,由i-1状态来推出i状态即可

注意要打好边际条件的状态,并且某个可行状态必须由前一个可行状态推出

/*
f[i][k][t]表示第i行状态为t,第i-1行状态为k的炮兵数
边际条件:第一行为任意可行状态即dp[1][1][i]=num[i]
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxn 110
char a[maxn][maxn];
int stk[maxn],cur[maxn],num[maxn],f[maxn][maxn][maxn];
int n,m,top;
inline bool legal(int x){//检查该状态是否会互相攻击
    if(x&(x<<1))return false;
    if(x&(x<<2))return false;
    return true;
}
inline bool fit(int x,int k){//检查第k行在x状态下是否在山地上
    if(x&cur[k])return false;
    return true;
}
inline void init(){//预处理,将合法的st存入stk中
    top=0;
    for(int i=0;i<=(1<<m)-1;i++)
        if(legal(i))stk[++top]=i;
}
inline int jcount(int x){//计数
    int cnt=0;
    while(x>0){cnt++;x&=(x-1);}
    return cnt;
}
int main(){
    cin>>n>>m;
    init();
    for(int i=1;i<=n;i++){
        scanf("%s",a[i]+1);
        for(int j=1;j<=m;j++)
            if(a[i][j]==‘H‘)
                cur[i]+=(1<<(m-j));//有山地的位置就是1
    }
    memset(f,-1,sizeof f);
    for(int i=1;i<=top;i++){//预处理第一行
        num[i]=jcount(stk[i]);
        if(fit(stk[i],1))f[1][1][i]=num[i];//如果这种状态可以放在第一行,那就摆下
        for(int j=2;j<=top;j++)f[1][j][i]=0;//第二行开始炮兵数设置为0
    }

    for(int i=2;i<=n;i++)
        for(int t=1;t<=top;t++){//枚举当前行的状态
            if(!fit(stk[t],i))continue;//第i行不能放状态stk[t]
            for(int j=1;j<=top;j++){//枚举i-2行的状态
                if(stk[t]&stk[j] || stk[j]&cur[i-2])continue;
                for(int k=1;k<=top;k++){
                    if(stk[t]&stk[k] || stk[j]&stk[k] || stk[k]&cur[i-1])continue;
                    if(f[i-1][j][k]==-1)continue;//i-1行的这种状态不可达
                    f[i][k][t]=max(f[i][k][t],f[i-1][j][k]+num[t]);
                }
            }
        }
    int ans=0;
    for(int i=1;i<=top;i++)
        for(int j=1;j<=top;j++)
            ans=max(ans,f[n][i][j]);
    cout<<ans<<endl;
}

原文地址:https://www.cnblogs.com/zsben991126/p/10357740.html

时间: 2024-10-08 14:13:24

poj1185 状态压缩经典题的相关文章

POJ-3254-Corn Fields-DP+状态压缩(入门题)

题目链接:http://poj.org/problem?id=3254 题目意思:给你一个n*m的牧场,叫你带牛去吃草,其中0代表没有草不可以放牧,1代表有草可以放牧.而且两头牛不可以相邻,叫你求所有可能的放牧方案. 思路:这是个状态压缩的基础题,刚学状态压缩的可以用这个题目来理解状态压缩:(如果是刚学DP我建议理解题意后先粗略的看一下代码后再边看代码边看我的思路,效果更佳) 1.题目告诉我们两头牛不能相邻,那么我们就可以枚举出每一行的所有情况,并且用数组st保存起来:怎么枚举每一种情况呢,题目

dp之状态压缩水题总结

状态压缩dp 其实就是 将状态表示成二进制,然后用位运算进行求解 poj 3311 Hie with the Pie Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5080   Accepted: 2706 Description The Pizazz Pizzeria prides itself in delivering pizzas to its customers as fast as possible. Unf

状态压缩经典题目(poj1184 nyoj81)

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

状态压缩简单题

状态压缩·一 题目传送:#1044 : 状态压缩·一 AC代码: #include <map> #include <set> #include <list> #include <cmath> #include <deque> #include <queue> #include <stack> #include <bitset> #include <cctype> #include <cstdi

hdu4064 三进制状态压缩 好题!

还不太会做这类题,总之感觉有点难啊. 用深搜代替打表求出一行所有的可行状态,注意要进行剪枝 这是自己理解的代码,但是tle了 #include<bits/stdc++.h> using namespace std; #define mod 1000000007 #define maxn 600005 int n,m,dp[2][maxn],sum; char mp[15][15][15]; int a[200],tag,flag,s[15]; // void dfs(int r,int num

Traveling by Stagecoach 状态压缩裸题

Traveling by Stagecoach dp[s][v]  从源点到达  v,状态为s,v的最小值.  for循环枚举就行了. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <string> 7 #include <vector>

HDU 1429 胜利大逃亡(续)(bfs+状态压缩,很经典)

传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1429 胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 10648    Accepted Submission(s): 3860 Problem Description Ignatius再次被魔王抓走了(搞不懂他咋这么讨魔王

状态压缩动态规划总结

状态压缩是一个很广的概念,在OI中也有很多的应用,当我们把他应用到动态规划中,可以用来精简状态,节约空间,也方便转移.最常见的就是用二进制来表是状态,利用各种位移运算,就可以实现\(O(1)\)的转移.状压DP适用于“窄棋盘”上的DP,否则状态太多无法存下. POJ1185 炮兵阵地 题意:给一个\(N \times M\)的地形盘,有平原和山坡,要求在平原上部署尽量多的炮(攻击范围2),使得不互相攻击. 数据范围:N <= 100:M <= 10,符合条件.如何表示状态?按行DP,一个二进制

[HDU]5094Maze(状态压缩BFS)

状态压缩的题,第一次WA了,怎么改都不对,交了十几遍,之后重新写了一个,1A了 #include<cstdio> #include<queue> #include<cstring> #include<algorithm> using namespace std; const int maxn = 51; const int dir[4][2] = {{0,1},{-1,0},{0,-1},{1,0}}; int n,m,t; int door[maxn][m