zoukankan      html  css  js  c++  java
  • 洛谷 P2704 炮兵阵地 【状压再状压dp】【北大ACM/ICPC竞赛训练】

    dp[i][j][k]代表前i层,第i层炮兵布局为j,第i-1层炮兵布局为k的最多摆放炮兵数。我们要记录两层的炮兵摆放,而且转移的时候要枚举第i-2层的状态m,使得m与j相容,m与k相容(当然也保证j与k相容),这样才满足无后效性。只要m满足相容的条件,那怎么从第1层到第i-3层摆放炮兵都无所谓了,因为第i层只能打到i-1层和i-2层,与dp[i-1][j][m]这样的方案数怎么达到的没有关系了。

    然后每行最多十列,所以每层的状态有1024种。

    dp[100][1024][1024]再加上枚举m的线性转移,炸了。

    为什么呢?每一层的状态真的有1024种吗?不是这样的,因为每个炮兵还能打左右两格的距离,所以实际上用二进制数每一位表示有没有炮兵来枚举浪费了计算(比如1110000000是不合法的根本没必要枚举)。我们可以dfs一下算出所有横向相容的状态数,发现10列而且都是平原,也只有60种合法状态。所以我们只考虑这60种就可以了

    dp[100][60][60]线性转移,再利用相容枚举的时候剪一剪枝就过了。

     1 #include<iostream>
     2 #include<cstring>
     3 using namespace std;
     4 
     5 char maze[105][15];
     6 int status[70],cnt,n,m;
     7 int dp[105][70][70];//dp[i][j][k]第i层布局为j,第i-1层布局为k,前i层的最多摆放炮兵数
     8                 //dp[i][j][k] = dp[i-1][k][枚举m] 使得m与j和k相容 
     9 int rong[70][70],rong2[105][70];
    10 int number[70],ans;
    11 
    12 int num(int s){
    13     int count=0;
    14     for(int i=1;i<=m;i++){
    15         if( s&(1<<i) ) count++;
    16     }
    17     return count;
    18 }
    19 
    20 void dfs(int col,int last_col,int state){//放到第col列    上一个放炮兵的地方在last_col   status是炮兵摆放的状态 
    21     if(col==m+1){
    22         status[++cnt]=state;
    23         number[cnt]=num(state);
    24         return;
    25     }
    26     if(last_col+3<=col) dfs(col+1,col,state+(1<<col) );//这一列放炮兵 
    27     dfs(col+1,last_col,state);//不放炮兵 
    28 }
    29 
    30 int check(int s1,int s2){//s1表示的状态是否与s2表示的状态相容
    31     if(rong[s1][s2]!=-1) return rong[s1][s2];
    32     int n1=status[s1],n2=status[s2]; 
    33     for(int i=1;i<=m;i++){//有没有在第i列上放炮兵
    34         if( (n1&(1<<i) ) && (n2&(1<<i)) ) return rong[s1][s2]=0;
    35     }
    36     return rong[s1][s2]=1;
    37 }
    38 
    39 int check2(int floor,int s){//能不能在第floor层的土地上放s
    40     if(rong2[floor][s]!=-1) return rong2[floor][s];
    41     int n1=status[s];
    42      for(int i=1;i<=m;i++){//有没有在第i列上放炮兵
    43         if( (n1&(1<<i) ) && maze[floor][i]=='H' ) return rong2[floor][s]=0;
    44     }
    45     return rong2[floor][s]=1;
    46 }
    47 
    48 int main(){
    49     memset(rong,-1,sizeof(rong));
    50     memset(rong2,-1,sizeof(rong2));
    51 
    52     cin>>n>>m;
    53     dfs(1,-2,0);
    54 
    55     for(int i=1;i<=n;i++)
    56      for(int j=1;j<=m;j++) cin>>maze[i][j];
    57     
    58     //考虑一行中(有m列)全为平地时,能放炮兵的所有合法状态
    59     for(int i=1;i<=cnt;i++) {
    60         if(check2(1,i)) {
    61             dp[1][i][0]=number[i];
    62             ans=max(ans,dp[1][i][0]);
    63         }
    64     }
    65     
    66     for(int i=1;i<=cnt;i++){
    67         if(check2(2,i) ){
    68             for(int j=1;j<=cnt;j++){//枚举上一层的状态 
    69                 if( check(i,j) && check2(1,j) ) {
    70                     dp[2][i][j]=dp[1][j][0]+number[i];
    71                     ans=max(ans,dp[2][i][j]);
    72                 }
    73             }
    74         }
    75     }
    76     //cout<<"!!!"<<endl;
    77     for(int i=3;i<=n;i++){
    78         for(int j=1;j<=cnt;j++){
    79             for(int k=1;k<=cnt;k++){
    80                 //dp[i][j][k] == 前i层,第i层摆放为j,第i-1层摆放为k == 最多摆放炮兵的数量 
    81                 for(int m=1;m<=cnt;m++){//枚举第i-2层的摆放情况 
    82                     if( check(m,j) && check(m,k) && check(j,k) && check2(i-2,m) && check2(i,j) && check2(i-1,k) ) {
    83                         dp[i][j][k]=max( dp[i][j][k] , dp[i-1][k][m]+number[j] );
    84                         ans=max(ans,dp[i][j][k]);
    85                     }
    86                 }
    87             }
    88         }
    89     }
    90     
    91     cout<<ans;
    92 
    93     return 0;    
    94 }
  • 相关阅读:
    linux ssh 安装、安全设置
    STL底层数据结构实现
    谷粒商城踩坑汇总(分布式高级篇)
    谷粒商城踩坑汇总(分布式基础(全栈开发篇))
    使用Vagrant 后发现虚拟机磁盘空间爆满的血泪填坑记
    Tomcat启动时,控制台和IDEA控制台中文乱码解决方案
    Unknown initial character set index '255' received from server. Initial client character set can be ... 解决方法
    idea打包成功但是resource下的文件没有复制到classes文件夹的解决方法
    tomcat控制台中文乱码怎么处理
    idea中tomcat启动时控制台中文乱码解决
  • 原文地址:https://www.cnblogs.com/ZhenghangHu/p/9397976.html
Copyright © 2011-2022 走看看