• hdu 4539 郑厂长系列故事——排兵布阵


    郑厂长系列故事——排兵布阵

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
    Total Submission(s): 1294    Accepted Submission(s): 470


    Problem Description
      郑厂长不是正厂长
      也不是副厂长
      他根本就不是厂长
      事实上
      他是带兵打仗的团长

      一天,郑厂长带着他的军队来到了一个n*m的平原准备布阵。
      根据以往的战斗经验,每个士兵可以攻击到并且只能攻击到与之曼哈顿距离为2的位置以及士兵本身所在的位置。当然,一个士兵不能站在另外一个士兵所能攻击到的位置,同时因为地形的原因平原上也不是每一个位置都可以安排士兵。
      现在,已知n,m 以及平原阵地的具体地形,请你帮助郑厂长计算该阵地,最多能安排多少个士兵。
     
    Input
    输入包含多组测试数据;
    每组数据的第一行包含2个整数n和m (n <= 100, m <= 10 ),之间用空格隔开;
    接下来的n行,每行m个数,表示n*m的矩形阵地,其中1表示该位置可以安排士兵,0表示该地形不允许安排士兵。
     
    Output
    请为每组数据计算并输出最多能安排的士兵数量,每组数据输出一行。
     
    Sample Input
    6 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
     
    Sample Output
    2
     
    Source
    // ans[] 里面存的是 m 个 1 能达到所有的状态 
    //如果 m == 2 , 则可以达到 00 01 10 11 既0,1,2,3
    // dp[i][j][k] 表示 计算到 第 i 行 状态是 ans[j] , 上一行 状态是 ans[k] ;
    // 然后枚举上一行的所有状态 和上一行判断是否有冲突 ,
    //可以把上一行的状态 向左和向右移一位(二进制),判断是否有同 1
    // 和上一行的上一行只要判断是否同为一就好了
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<cmath>
    #include<set>
    #include<algorithm>
    #define maxn 110
    #define INF 100
    #define LL long long
    #define mod 1000000007
    using namespace std ;
    
    int len , f[14],m ,num[200],n;
    int ans[200] , dp[110][172][172] ;
    bool vi[1025] , map1[110][11] ;
    void dfs( int cur , int sum , int a , int mm )
    {
        if(cur > m )
        {
             num[len] = mm ;
             ans[len++] = sum ;
            return ;
        }
        dfs(cur+1,sum,a+1,mm) ;
        if(cur >= 3 && f[cur-2] == 1 ) return ;
        f[cur] = 1 ;
        dfs(cur+1,sum+(1<<a),a+1,mm+1) ;
        f[cur] = 0 ;
    }
    int get( int cur )//返回cur 行可以达到最大的状态值是多少
    {
        int ans = 0, i;
        for( i = 0 ; i < m ;i++ )
        {
            if(map1[cur][i+1]) ans += (1<<i) ;
        }
        return ans ;
    }
    bool check1( int b , int a )
    {
        int a1 , a2 ;
        a1 = a<<1 ;a2 = a>>1 ;
        if((a1&b)||(a2&b)) return false ;
        return true ;
    }
    bool check2( int a , int b )
    {
        if(a&b) return false ;
        return true ;
    }
    int main()
    {
        int i , j ,aa , bb , k , v ;
        int Max ;
         //freopen("in.txt","r",stdin) ;
        while( scanf("%d%d" , &n , &m ) != EOF )
        {
            len = 1 ;
            memset(f,0,sizeof(f)) ;
            //枚举所有状态
            dfs(1,0,0,0) ;
            sort(ans+1,ans+len) ;
          //  for( i = 1 ; i < len ;i++)cout << ans[i] << " " ;
            for( i = 1 ; i <= n ;i++ )
                for( j = 1 ; j <= m ;j++ )
            {
                scanf("%d",&aa) ;
                if(aa==1)map1[i][j] = 1 ;
                else map1[i][j] = 0 ;
            }
            bb = get(1) ;
            Max = 0 ;
            memset(dp,0,sizeof(dp)) ;
            for( i = 1 ; i < len ;i++ )if((ans[i]|bb) <= bb )//如果 ans[i] 可达, 既 bb 为一的 ans[i] 可以为 1 ,为0 的 ans[i] 只可以为 0
            {
                for( j = 1 ; j < len ;j++ )
                   dp[1][i][j] = num[i] ;
            }
            for( i = 2 ; i <= n ;i++ )
                for( j = 1 ; j < len ;j++ )
            {
                bb = get(i) ;
                if((bb|ans[j]) > bb )continue ;
                for( k = 1 ; k < len ;k++ )if(check1(ans[j],ans[k])||bb==0)
                    for( v = 1 ; v < len ;v++ )if(check2(ans[j],ans[v])||bb==0){
                        dp[i][j][k] = max(dp[i][j][k],dp[i-1][k][v]+num[j]) ;
    
                    }
            }
            for( i = 1 ; i < len ;i++ )
                for( j = 1 ; j < len ;j++ )
                Max = max(Max,dp[n][i][j]) ;
         cout << Max << endl;
        }
    }
    
  • 相关阅读:
    vim 命令详解
    vim基础命令
    JSP取得绝对路径
    sigar开发(java)
    HDU-5273
    HDU-1671
    HDU-1251
    POJ-1743
    POJ-2774
    hihocoder 1145 : 幻想乡的日常
  • 原文地址:https://www.cnblogs.com/20120125llcai/p/3387369.html
Copyright © 2020-2023  润新知