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

    状态压缩dp。

    一开始想开个dp[2][1024][1024]的数组,显然开不下,而且也会超时。

    因此把状态对应放在另外一个数组s里。

    map[i]表示用二进制表示第i行的地势情况,1是高地,0是平原。

    用dp[i][j][k]表示第i行,达到状态s[j],且i-1行的状态是s[k]的最优解。

    状态转移方程为 dp[i][j][k]=max(dp[i][j][k],dp[i-1][k][p]+cnt[j]);

    满足状态转移方程的条件是 s[j]&map[i]==0,s[j]&s[k]==0,s[j]&s[p]==0,且dp[i-1][k][p]存在。

    //Memory:228K
    //Time:422ms
    
    
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    int n,m;
    int map[110];
    int dp[2][110][110];
    int s[110],scnt,cnt[110];
    
    void DFS(int dta,int dep)
    {
        bool ok=1;
        if(10==dep) {
            s[scnt++]=dta;
            return;
        }
        if(dep) {
            if((1<<(dep-1))&dta)
                ok=0;
            if(dep>1) {
                if((1<<(dep-2))&dta)
                    ok=0;
            }
        }
        if(ok) DFS(dta|(1<<dep),dep+1);
        DFS(dta,dep+1);
    }
    
    void init()
    {
        DFS(0,0);
        sort(s,s+scnt);
        s[scnt]=0x3f3f3f3f;
        for(int i=0;i<scnt;++i) {
            cnt[i]=0;
            for(int j=0;j<10;++j)
                if((1<<j)&s[i]) ++cnt[i];
        }
    }
    
    int main()
    {
        init();
        char str[12];
        int hehe;
        int now,before;
        int ans;
        while(scanf("%d%d",&n,&m)==2) {
            memset(map,0,sizeof map);
            memset(dp,-1,sizeof dp);
            dp[0][0][0]=0;
            for(int i=1;i<=n;++i) {
                scanf("%s",str);
                for(int j=0;j<m;++j)
                    if(str[j]=='H') map[i]|=(1<<(m-j-1));
            }
            hehe=1<<m;
            for(int i=1;i<=n;++i) {
                now=i&1;
                before=now?0:1;
                for(int j=0;s[j]<hehe;++j) {
                    if(s[j]&map[i]) continue;
                    for(int k=0;s[k]<hehe;++k) {
                        if(s[j]&s[k]) continue;
                        dp[now][j][k]=0;
                        for(int p=0;s[p]<hehe;++p) {
                            if(s[j]&s[p]||dp[before][k][p]==-1) continue;
                            dp[now][j][k]=max(dp[now][j][k],dp[before][k][p]+cnt[j]);
                        }
                    }
                }
            }
            ans=0;
            for(int i=0;s[i]<hehe;++i) {
                for(int j=0;s[j]<hehe;++j)
                    ans=max(ans,dp[now][i][j]);
            }
            printf("%d\n",ans);
        }
    }
  • 相关阅读:
    Go 模板
    使用Go开发web服务器
    CLI:使用Go开发命令行应用
    MyBatis 注解使用动态SQL
    Tomcat 使用Redis存储Session
    [翻译] java NIO Buffer
    [翻译] java NIO Channel
    [翻译]java nio 概述
    [翻译] java NIO 教程---介绍
    接口的定义常量与使用
  • 原文地址:https://www.cnblogs.com/morimiya/p/3385266.html
Copyright © 2011-2022 走看看