zoukankan      html  css  js  c++  java
  • 2019.9.1 炮兵阵地

    传送门

    明显状压dp 用dp[i][j][k]记录前i行最后一行状态编号是j且倒数第二行状态编号是k最多能放几个

    所以我们先初始化dp[1]和dp[2]

    其中dp[1][j][0]=bj[1][j] 因为第0行可以当做没选

    dp[2][j][k]=bj[1][j]+bj[2][k] bj数组的意义同下文

    则当i>2时 dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+bj[i][j])

    其中l是枚举的倒数第三行的状态编号,bj[i][j]表示第i行的第j个状态放了多少个

    上代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define int long long
    using namespace std;
    int num[105][(1<<10)+1],bj[105][(1<<10)+1],ans,n,m,mapp[105][15],dp[105][(1<<10)+1][(1<<10)+1];
    bool check(int r,int x)
    {
        for(int i=m;i>=1;i--)
        {
            if(!mapp[r][i]&&(x&1))return false;
            x>>=1;
        }
        return true;
    }//检查状态是否合法
    int getnum(int r,int x)
    {
        int res=0;
        while(x)res+=x&1,x>>=1;
        return bj[r][num[r][0]]=res;
    }//初始化bj数组
    signed main()
    {
        scanf("%lld%lld",&n,&m);
        char ch;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                cin>>ch;
                if(ch=='P')mapp[i][j]=1;
                else mapp[i][j]=0;
            }
        }
        int maxn=(1<<m)-1;
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<=maxn;j++)
            {
                if(check(i,j)&&!(j&(j<<1))&&!(j&(j<<2)))
                {
                    num[i][++num[i][0]]=j;//num[i][j]表示第i行编号为j的状态是什么,num[i][0]表示这一行有多少个合法状态
                    if(i==1)dp[i][num[i][0]][0]=getnum(i,j);
                    bj[i][num[i][0]]=getnum(i,j);
                }
            }
        }
        for(int i=1;i<=num[2][0];i++)
        {
            for(int j=1;j<=num[1][0];j++)
            {
                int x=num[2][i],y=num[1][j];
                if(x&y)continue;
                dp[2][i][j]=max(dp[2][i][j],bj[2][i]+bj[1][j]);
            }
        }//枚举上下两行,初始化dp[2]
        for(int i=3;i<=n;i++)
        {
            for(int j=1;j<=num[i][0];j++)
            {
                for(int k=1;k<=num[i-1][0];k++)
                {
                    for(int l=1;l<=num[i-2][0];l++)
                    {
                        int x=num[i][j],y=num[i-1][k],z=num[i-2][l];
                        if((x&y)||(y&z)||(x&z))continue;
                        dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][l]+bj[i][j]);
                    }
                }
            }
        }//枚举这一行、上一行、上上行
        for(int i=1;i<=num[n][0];i++)
        {
            for(int j=1;j<=num[n-1][0];j++)
            {
                int x=num[n][i],y=num[n-1][j];
                if(x&y)continue;
                ans=max(ans,dp[n][i][j]);
            }
        }//枚举这一行和上一行的可能
        printf("%lld",ans);
        return 0;
    }
    /*====年轻人,瞎搞是出不了省一的,这就是现实====*/
  • 相关阅读:
    linux --- mysql --- max_allowed_packet
    idea 快捷键
    TypedArray和obtainStyledAttributes使用
    ubuntu中怎样添加或删除一个PPA源
    Ubuntu 14.04 用户安装 Cinnamon 2.2.0
    android-pulltorefresh源码解析(1)--PullToRefreshListView的使用
    Android菜单详解(四)——使用上下文菜单ContextMenu
    Android菜单详解(五)——使用XML生成菜单
    Android菜单详解(二)——创建并响应选项菜单
    Android菜单详解(三)——SubMenu和IconMenu
  • 原文地址:https://www.cnblogs.com/qxds/p/11443399.html
Copyright © 2011-2022 走看看