zoukankan      html  css  js  c++  java
  • poj1185炮兵阵地

    题目链接:传送门

    题目思路:状态压缩DP(详见注释)

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <cstring>
    #include <stack>
    #include <cctype>
    #include <queue>
    #include <string>
    #include <vector>
    #include <set>
    #include <map>
    #include <climits>
    #define lson root<<1,l,mid
    #define rson root<<1|1,mid+1,r
    #define fi first
    #define se second
    #define seg int root,int l,int r
    #define ping(x,y) ((x-y)*(x-y))
    #define mst(x,y) memset(x,y,sizeof(x))
    #define mcp(x,y) memcpy(x,y,sizeof(y))
    #define Min(x,y) (x<y?x:y)
    #define Max(x,y) (x>y?x:y)
    using namespace std;
    #define gamma 0.5772156649015328606065120
    #define MOD 100000007
    #define inf 0x3f3f3f3f
    #define N 10005
    #define maxn 1000050
    typedef long long LL;
    typedef pair<int,int> PII;
    
    char str[105];
    int pic[105],n,m,ans,all;
    int state[1005],num[1005],cnt;///state里面保存的是可以放炮台的情况
    int dp[105][105][105];        ///二进制位为1表示放炮台,和pic中的不一样
    
    int judge(int x){           ///判断x是否满足左右两格之内没有炮台
        if((x&(x<<1))||(x&(x<<2)))return 0;
        int res=0;              ///如果符合条件统计该情况下放了多少炮台
        while(x){
            res+=(x&1);
            x>>=1;
        }
        num[cnt]=res;
        return 1;
    }
    void init(){                        ///初始化有多少个状态符合题意(每个点左右两格之内无炮台)
        cnt=0;
        for(int i=0;i<all;++i)
            if(judge(i))
                state[cnt++]=i;
    }
    
    int main(){
        int i,j,k,l;
        while(scanf("%d%d",&n,&m)!=EOF){
            mst(pic,-1);                ///-1在计算机中二进制表示为全1,,初始化这样做的好处当n为1时不用出错
            mst(dp,0);                  ///因为pic[2]二进制全都为1,没有一个状态满足
            all=1<<m;
            for(i=1;i<=n;++i){
                pic[i]=0;
                scanf("%s",str);
                for(j=0;j<m;++j)
                    pic[i]=pic[i]<<1|(str[j]=='P'?0:1); ///这里为0可以放炮台,为1不能放
            }
            ans=0;
            init();
            for(i=0;i<cnt;++i){                 ///初始化第一行状态
                if(pic[1]&state[i])continue;
                dp[1][i][0]=num[i];
                ans=Max(ans,num[i]);            /*****/ ///注意从这就要开始保存答案,不然会WA
            }
            for(i=0;i<cnt;++i){                 ///第二行状态
                if(pic[2]&state[i])continue;    ///在这里体现出了初始化为-1的好处,当n==1时,不会错
                for(j=0;j<cnt;++j){         
                    if(pic[1]&state[j])continue;
                    dp[2][i][j]=Max(dp[2][i][j],dp[1][j][0]+num[i]);
                    ans=Max(ans,dp[2][i][j]);
                }
            }
            for(i=3;i<=n;++i){
                for(j=0;j<cnt;++j){ ///第i行状态
                    if(pic[i]&state[j])continue; ///选取的state与pic冲突,不可取,下面同理
                    for(k=0;k<cnt;++k){///第i-1行状态
                        if(state[j]&state[k])continue;
                        if(state[k]&pic[i-1])continue;
                        for(l=0;l<cnt;++l){///第i-2行状态
                            if(state[l]&pic[i-2])continue;
                            if(state[l]&state[k])continue;
                            if(state[l]&state[j])continue;
                            dp[i][j][k]=Max(dp[i][j][k],dp[i-1][k][l]+num[j]);
                            ans=Max(ans,dp[i][j][k]);
                        }
                    }     ///要dp数组的维度所表示的意义,i表示第几行,j表示在第i行选取的是状态state[j]
                }         ///k表示i-1行选取的是state[k]状态,因为上面两行对当前行都会有影响
            }             ///所以更新状态时才会有那么多判断
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    闭包函数 (字符编码,文件处理,函数基础总结)
    函数参数详解
    文件处理及函数基础
    文件处理高级
    面向对象----反射
    正则表达式与re模块
    常用模块
    模块和包
    内置函数与匿名函数
    HDU
  • 原文地址:https://www.cnblogs.com/Kurokey/p/5474508.html
Copyright © 2011-2022 走看看