zoukankan      html  css  js  c++  java
  • 状态压缩动态规划 -- 炮兵阵地


    司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队,一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),例如以下图。在每一格平原地形上最多可以布置一支炮兵部队(山地上不可以部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所看到的:


    假设在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它可以攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其他白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响。如今,将军们规划怎样部署炮兵部队,在防止误伤的前提下(保证不论什么两支炮兵部队之间不能互相攻击,即不论什么一支炮兵部队都不在其他支炮兵部队的攻击范围内),在整个地图区域内最多可以摆放多少我军的炮兵部队。


    题目链接:http://poj.org/problem?id=1185


    #include <iostream>
    #include <cstring>
    using namespace std;
    #define MAX_SIZE 110
    int graph[MAX_SIZE];
    int DP[MAX_SIZE][MAX_SIZE][MAX_SIZE];
    // DP[raw][i][j] : 在第 raw 行状态为 i, 第 raw - 1 行状态为 j 的情况
    int pointer, state_stack[MAX_SIZE], ones_num[MAX_SIZE];
    
    // 推断该状态左右相邻两个单位是否有炮兵冲突
    bool isReasonableState( int state ){
        if( state & ( state << 1 ) )
            return false;
        if( state & ( state << 2 ) )
            return false;
        return true;
    }
    
    // 计算比特位里的 1 的个数
    int getOnesNum( int state ){
        int num = 0;
        while( state > 0 ){
            if( state & 1 )
                num++;
            state >>= 1;
        }
        return num;
    }
    
    // 预处理,统计下全部“行”摆放炮兵的合法状态
    void pretreatment( int cols ){
        int max_state = ( 1 << cols ) - 1;
        for( int state = 0; state <= max_state; ++state ){
            if( isReasonableState( state ) ){
                state_stack[pointer] = state;
                ones_num[pointer]    = getOnesNum( state );
                pointer++;
            }
        }
    }
    
    int main(){
        memset( DP, -1, sizeof( DP ) );
        memset( graph, 0, sizeof( graph ) );
        pointer = 0;
    
        int raws, cols;
        cin >> raws >> cols;
        pretreatment( cols );
    
        for( int raw = 0; raw < raws; ++raw ){
            for( int col = 0; col < cols; ++col ){
                char c;
                cin >> c;
                if( c == 'H' )
                    graph[raw] |= ( 1 << col );
            }
        }
    
        for( int p = 0; p < pointer; ++p )
            if( !( state_stack[p] & graph[0] ) )
                DP[0][p][0] = ones_num[p];
    
        for( int raw = 1; raw < raws; ++raw ){
            for( int raw_p = 0; raw_p < pointer; ++raw_p ){
                if( state_stack[raw_p] & graph[raw] )
                    continue;
                for( int raw_p_ = 0; raw_p_ < pointer; ++raw_p_  ){
                    if( state_stack[raw_p] & state_stack[raw_p_] )
                        continue;
                    for( int raw_p__ = 0; raw_p__ < pointer; ++raw_p__ ){
                        if( state_stack[raw_p] & state_stack[raw_p__] )
                            continue;
                        if( DP[raw - 1][raw_p_][raw_p__] == -1 )
                            continue;
                        DP[raw][raw_p][raw_p_] = max( DP[raw][raw_p][raw_p_],
                                                DP[raw - 1][raw_p_][raw_p__] + ones_num[raw_p] );
                    }
                }
            }
        }
        int ans = 0;
        for( int raw_p = 0; raw_p < pointer; ++raw_p )
            for( int raw_p_ = 0; raw_p_ < pointer; ++raw_p_ )
                ans = max( ans, DP[raws - 1][raw_p][raw_p_] );
    
        cout << ans << endl;
        return 0;
    }
    


  • 相关阅读:
    Proj THUDBFuzz Paper Reading: PMFuzz: Test Case Generation for Persistent Memory Programs
    入围 WF 后训练记
    算法竞赛历程
    2021 多校 杭电 第十场
    2021 多校 杭电 第九场
    2021 多校 牛客 第十场
    2021 多校 牛客 第九场
    2021 多校 杭电 第八场
    2021 多校 杭电 第六场
    2021 多校 杭电 第七场
  • 原文地址:https://www.cnblogs.com/blfshiye/p/4076957.html
Copyright © 2011-2022 走看看