poj1185:炮兵阵地(状压dp)

也算是比较基础的状压dp了,跟做过的第二道比较又稍微复杂了一点

需要记录之前两行的状态。。

统计结果也稍有不同

另外还学习了一个得到一个整数二进制位 1 的个数的位运算方法

详见代码:

#include <iostream>

#include <stdio.h>

#include<string.h>

#include<algorithm>

#include<string>

#include<ctype.h>

using namespace std;

#define MAXN 10000

int s[70];

int num[70];

int cant[110];

int dp[110][70][70];

int ns;

int n,m;

int ct(int x)

{

    int res=0;

    while(x)

    {

        res++;

        x&=(x-1);

    }

    return res;

}

void setstate()

{

    memset(num,0,sizeof(num));

    for(int i=0;i<1<<10;i++)

    {

        if((i&(i<<1))==0&&((i&(i<<2))==0))

        {

            s[ns]=i;

            num[ns++]=ct(i);

        }

    }

}

void ini()

{

    memset(cant,0,sizeof(cant));

    char s[20];

    for(int i=1;i<=n;i++)

    {

        scanf("%s",s);

        for(int j=0;j<m;j++)

        {

            if(s[j]=='H')

            {

                cant[i]|=(1<<j);

            }

        }

    }

}

void solve()

{

    memset(dp,0,sizeof(dp));

    for(int i=0;i<ns&&s[i]<(1<<m);i++)

    {

        if((s[i]&cant[1])==0)

            dp[1][0][i]=num[i];

    }

    for(int i=2;i<=n;i++)

    {

        for(int t=0;t<ns&&s[t]<(1<<m);t++)

        {

            if(s[t]&cant[i])

                continue;

        for(int j=0;j<ns&&s[j]<(1<<m);j++)

        {

            if(s[j]&cant[i-2])

                continue;

            for(int k=0;k<ns&&s[j]<(1<<m);k++)

            {

                if(s[k]&cant[i-1])

                    continue;

                if(s[j]&s[k])

                    continue;

                if(s[t]&cant[i])

                    continue;

                if((s[t]&s[j])||(s[t]&s[k]))

                    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<ns&&s[j]<(1<<m);j++)

        {

            for(int k=0;k<ns&&s[k]<(1<<m);k++)

                ans=max(ans,dp[i][j][k]);

        }

    }

    printf("%d\n",ans);

}

int main()

{

    ns=0;

    setstate();

    while(scanf("%d%d",&n,&m)!=EOF)

    {

        ini();

        solve();

    }

    return 0;

}

 

你可能感兴趣的:(poj)