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

题目链接

     如果你是刚刚开始做状态压缩dp,我建议你先看看 poj 3254 Corn Fields 这是一道比这一题更简单,更容易入门的题目。
    还有在代码中我用了一个很巧妙的方法求一个数二进制数中1的个数  具体请看我博客中  x& (x - 1)==0 这篇文章  链接  。
     还有一点,不同于poj 3254的地方,我们不能直接枚举所有的状态。我在getresult()中用到了四重循环,直接枚举的时间复杂度是2^40,并且dp那个数组也是开不下到,不过对于这道题还是有方法的。枚举一行所有的状态,行合法(没有两个1相隔少于两个)的状态总共有61中,我们只需要枚举所有合法状态即可,循环次数最多是61^4。

代码

#include 
#include 
#include 
using namespace std;

const int maxn = 62;          //每行合法的状态总共有61种
int dp[102][maxn][maxn];      //因为状态是与前两行有关,所以用到三维数组
int sta[102];                 //每行不能放置的点
int cnt[maxn];                //状态中1的数目,也就是炮的数目
int allsta[maxn];             //所有可能的状态
int n, m;
int num;                      //满足条件的状态数

bool judgeself(int x)         //判断x状态是不是有会相互攻击的状态,也就是有没有两个1相隔少于两个0
{
    if (x&(x<<1) || x&(x<<2))
        return false;
    return true;
}

int count(int x)              //用很巧妙的计算出x二进制中1的个数
{
    int s = 0;
    while (x)
    {
        s++;
        x = x&(x-1);
    }
    return s;
}

void search(int x)
{                                   //这个函数相当于把对状态进行了离散化,去掉了每行所有不合法的状态
    int t = 1<


转载于:https://www.cnblogs.com/xindoo/archive/2013/05/08/3595137.html

你可能感兴趣的:(poj 1185 炮兵阵地 (状态压缩dp))