poj 1185 炮兵阵地

来源:互联网 发布:mac电脑卡机怎么解决 编辑:程序博客网 时间:2024/06/03 12:17

poj 1185 炮兵阵地

刚刚学习状态压缩,看到这样的问题真的有些不知所措

所以看了大神的题解,得到了这种题的解题思路

这个题的状态就是每一行的炮兵阵地摆放不能相邻,或者仅隔一个位置

找出每一行的状态数最多是sum=60个左右(当列数为10时)

每一行的状态都受起那两行的状态影响,所以不难得出算法的时间复杂度为n*sum^3

/**初学状态压缩题目:poj 1185 炮兵阵地解决方法:状态压缩,滚动数组*/#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>using namespace std;char c[105][15];int a[105]; //记录每行状态int state[70],cor=0;int num[70];//记录每个状态的炮兵数int dp[70][70][2];int fun(int num){    int ans=0;    while(num){        if(num%2)ans++;        num/=2;    }    return ans;}void Init(){    //不含相邻的和仅隔一个位置的炮兵阵地    for(int i=0;i<(1<<10);i++)        if((i&(i<<1))==0 && (i&(i<<2))==0 &&            (i&(i>>1))==0 && (i&(i>>2))==0){            state[cor]=i;            num[cor++]=fun(i);        }}int main(){    Init();    int n,m;    while(~scanf("%d%d",&n,&m)){        for(int i=0;i<n;i++){            scanf("%s",c[i]);            a[i]=0;            for(int j=0;j<m;j++){                a[i]<<=1;                if(c[i][j]=='H') a[i]|=1;            }        }        memset(dp,-1,sizeof(dp));        dp[0][0][0]=0;        int now=0,top=1<<m;        for(int i=0;i<n;i++){//依次遍历每一行更新每一个状态值            for(int j=0;j<cor&&state[j]<top;j++)                for(int k=0;k<cor&&state[k]<top;k++)                    if(dp[j][k][now]!=-1)                    for(int t=0;t<cor&&state[t]<top;t++)                        if((a[i]&state[t])==0&&                           (state[t]&state[j])==0&&                           (state[t]&state[k])==0)                        dp[k][t][now^1]=max(dp[k][t][now^1],                                    dp[j][k][now]+num[t]);            now^=1;        }        int ans=0;        for(int i=0;i<cor&&state[i]<top;i++)            for(int j=0;j<cor&&state[j]<top;j++)                ans=max(dp[i][j][now],ans);        printf("%d\n",ans);    }    return 0;}


0 0