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);
        }
    }
  • 相关阅读:
    动态规划——Best Time to Buy and Sell Stock IV
    动态规划——Split Array Largest Sum
    动态规划——Burst Ballons
    动态规划——Best Time to Buy and Sell Stock III
    动态规划——Edit Distance
    动态规划——Longest Valid Parentheses
    动态规划——Valid Permutations for DI Sequence
    构建之法阅读笔记05
    构建之法阅读笔记04
    构建之法阅读笔记03
  • 原文地址:https://www.cnblogs.com/morimiya/p/3385266.html
Copyright © 2011-2022 走看看