zoukankan      html  css  js  c++  java
  • POJ

    题目大意:中文题目就不多说大意了

    解题思路:
    1.每行最多仅仅有十个位置,且不是山地就是平原,那么就能够用1表示山地,0表示平原,将每一行的状态进行压缩了

    2.接着找出每行能放炮兵的状态。先不考虑其它行放炮兵和该行的山地对其造成的影响,枚举出全部的状态。并记录每一个状态下放的炮兵数量
    在上述情况下放炮兵。仅仅须要考虑同行的炮兵是否会相互攻击就能够了,那仅仅须要推断他的左边第一个位置是否有炮兵和左边第二个位置是否有炮兵就可以

    3.接着进行dp,由于影响因素有两个。一个是上一行的状态,还有一个是上两行的状态,所以设dp[row][i][j]为第row行,放置状态为i,第row-1行,放置状态为j的情况下所能放的最多炮兵数量
    可得到转移方程,在前两行不影响该行放置的
    dp[row][i][j] = max(dp[row][i][j], dp[row-1][j][k] + i状态下能放置的炮兵数)

    參考了这位大神的代码,写得很得具体这里写链接内容

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define maxn 110
    #define maxm 20
    #define maxs 70
    int R, C, cnt;
    char str[15];
    int row[maxn], num[maxn], statu[maxn];
    int dp[maxn][maxs][maxs];
    
    void input() {
    
        memset(row, 0, sizeof(row));
        for(int i = 0; i < R; i++) {
            scanf("%s", str);
            for(int j = 0; j < C; j++)
                if(str[j] == 'H')
                    row[i] += (1 << j);
        }
    }
    
    void init_statu() {
    
        memset(num, 0, sizeof(num));
        cnt = 0;
        for(int i = 0; i < (1 << C); i++) {
            if((i & (i << 1)) || (i & (i << 2)))
                continue;
            int t = i;
            while(t) {
                num[cnt] += (t & 1);
                t >>= 1;
            }
            statu[cnt++] = i;
        }
    }
    
    void init_DP() {
    
        memset(dp, 0, sizeof(dp));
        for(int i = 0; i < cnt; i++) {
            if(statu[i] & row[0])
                continue;
            dp[0][i][0] = num[i];
        }
    
        for(int i = 0; i < cnt; i++)  {
            if(statu[i] & row[1])
                continue;
    
            for(int j = 0; j < cnt; j++) {
                if(statu[j] & row[0])
                    continue;
                if(statu[i] & statu[j])
                    continue;
                dp[1][i][j] = max(dp[1][i][j], dp[0][j][0] + num[i]);
            }
        }
    }
    
    int solve() {
        for(int r = 2; r < R; r++) {
            for(int i = 0; i < cnt; i++) {
                if(statu[i] & row[r])
                    continue;
                for(int j = 0; j < cnt; j++) {
                    if(statu[j] & row[r - 1])
                        continue;
                    if(statu[i] & statu[j])
                        continue;
                    for(int k = 0; k < cnt; k++) {
                        if(statu[k] & statu[j])
                            continue;
                        if(statu[k] & statu[i])
                            continue;
                        if(statu[k] & row[r - 2])
                            continue;
                        dp[r][i][j] = max(dp[r][i][j], dp[r - 1][j][k] + num[i]);
                    }
                }
            }
        }
        int ans = 0;
        for(int i = 0; i < cnt; i++)
            for(int j = 0; j < cnt; j++)
                ans = max(ans, dp[R-1][i][j]);
        return ans;
    }
    
    int main() {    
        while(scanf("%d%d", &R, &C) != EOF) {
            input();
            init_statu();
            init_DP();
            printf("%d
    ", solve());
        }
        return 0;
    }
    
  • 相关阅读:
    .NET基础篇——利用泛型与反射更新实体(ADO.NET Entity Framework)(转)
    反射奥秘
    ubuntu 安装chmsee
    ubuntu安装sublime,新立得
    Ubuntu 升级VisualBox后无法启动 Kernel driver not installed
    ubuntu安装stardict并导入词典
    PHP运行模式
    Ubuntu ibus输入法图标消失的解决办法
    MySQL 获得当前日期时间(以及时间的转换)
    mysql索引之or条件
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5186980.html
Copyright © 2011-2022 走看看