zoukankan      html  css  js  c++  java
  • 【Luogu】P2704炮兵阵地(状压DP)

      题目链接

      话说还真没见过能影响两行的状压。想了半天想出来f数组再多一维就能表示,但是没想到怎么才能不爆空间……

      也是从这道题里学到的一个妙招。

      可以把合法状态存到一个数组里,然后用数组下标来映射状态。感觉好强啊

      然后……这题差不多就完了。

      

    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    inline int getlen(int x){
        int ans=0;
        while(x){
            if(x&1)    ans++;
            x>>=1;
        }
        return ans;
    }
    
    int f[110][70][70];
    int s[70],w[70],cnt;
    int state[110];
    int Ans;
    int main(){
        int n=read(),m=read();
        int Max=(1<<m)-1;
        for(int i=1;i<=n;++i){
            char c[11];
            scanf("%s",c+1);
            for(int j=1;j<=m;++j){
                state[i]=state[i]<<1;
                if(c[j]=='H')    state[i]++;
            }
        }
        for(int i=0;i<=Max;++i){
            if(i&(i>>1)||i&(i>>2))    continue;
            s[++cnt]=i;
            w[cnt]=getlen(i);
            if(!(state[1]&i))    f[1][cnt][1]=w[cnt];
        }
        for(int i=1;i<=cnt;++i)
            for(int j=1;j<=cnt;++j){
                if(s[i]&s[j]||state[2]&s[i]||state[1]&s[j])    continue;
                f[2][i][j]=w[i]+w[j];
            }
        for(int i=3;i<=n;++i)
            for(int j=1;j<=cnt;++j){
                if(state[i]&s[j])    continue;
                for(int k=1;k<=cnt;++k){
                    int ans=0;
                    if((state[i-1]&s[k])||(s[j]&s[k]))    continue;
                    for(int l=1;l<=cnt;++l){
                        if((state[i-2]&s[l])||(s[j]&s[l])||(s[k]&s[l]))    continue;
                        ans=std::max(ans,f[i-1][k][l]);
                    }
                    f[i][j][k]=ans+w[j];
                }
            }
        for(int i=1;i<=cnt;++i)
            for(int j=1;j<=cnt;++j)    Ans=std::max(Ans,f[n][i][j]);
        printf("%d",Ans);
        return 0;
    }
  • 相关阅读:
    TCP/IP——IP网络协议简记
    TCP/IP——基础概念简记
    TCP/IP——链路层简记
    linux——(8)数据流重定向、管道命令
    linux——(7)了解shell
    linux——(6)vim与vi
    linux——(5)文件与文件系统的压缩与打包
    linux——(4)磁盘与文件系统管理
    linux——(3)文件与目录管理
    大数据--Spark原理
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/7613498.html
Copyright © 2011-2022 走看看