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

      压前两行的状态很容易想到,但是 直接搞  (1<<10) * (1<<10)  空间时间都明显受不了, 但是经过高人指点,你会发现:枚举每一行可行的状态,其实并不多,预先打表处理,不用 1->(1<<10)枚举每一种状态。。

    然后记忆化搜就ok了。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <climits>
    #include <string>
    #include <iostream>
    #include <map>
    #include <cstdlib>
    #include <list>
    #include <set>
    #include <queue>
    #include <stack>
    using namespace std;
    
    int deal(int a,int b)
    {
        return (a&(1<<b));
    }
    int m,n;
    int chart[1000];
    int vis[111];
    int len;
    int Map[111];
    int dp[111][222][222];
    int Max(int a,int b)
    {
        return a>b? a:b;
    }
    
    int Min(int a,int b)
    {
        return a>b?b:a;
    }
    int judge(int x)
    {
        for(int i=0;i<m;i++)if(deal(x,i)){
            int t= Max(0,i-2);int t1=Min(m-1,i+2);
            for(int j=t;j<=t1;j++){
            if(i==j) continue;
            if(deal(x,j)) return 0;
            }
        }
        return 1;
    }
    void Init()
    {
        int gg=1<<m;
        for(int i=0;i<gg;i++){
            if(judge(i))chart[len++]=i;
        }
    }
    
    int panduan(int x,int yici,int erci,int mat)
    {
        if(yici&x) return 0;  
        if(erci&x) return 0;// 与之前两排判重
        if(x&(~mat)) return 0;// 与原地图判重 Gxwar 提醒了我。。这个自己想了下,之前那个戳的写法让我不忍直视。  
       // for(int i=0;i<m;i++) if(deal(x,i)) if(!deal(mat,i)) return 0;
        return 1;
    }
    int gao(int x,int yici,int erci)
    {
        if(~dp[x][yici][erci]) return dp[x][yici][erci];
        if(x==n) return dp[x][yici][erci]= 0;
        int ret=0;
        for(int i=0;i<len;i++){
            if(panduan(chart[i],chart[yici],chart[erci],Map[x])) ret=Max(ret,gao(x+1,i,yici)+vis[i]);
        }
        return dp[x][yici][erci]= ret;
    }
    void Init1()
    {
        memset(vis,0,sizeof(vis));
        for(int i=0;i<len;i++){
            int tem=chart[i];int ans=0;
            for(int j=0;j<m;j++){
                if(tem&1) ans++;
                tem>>=1;
            }
            vis[i]=ans;
        }
    }
    int main()
    {
        char str[1000];
        while(cin>>n>>m){
            len=0;
            Init();Init1();
            memset(dp,-1,sizeof(dp));
            memset(Map,0,sizeof(Map));
            for(int i=0;i<n;i++){
                scanf("%s",str);
                for(int j=0;j<m;j++){
                    if(str[j]=='P')Map[i]|=(1<<j);
                }
            };
            cout<<gao(0,0,0)<<endl;
        }
        return 0;
    }
  • 相关阅读:
    进程空间与系统空间(一)
    内核之最
    Linux 内核3.10.5 专场
    device_create与device_register
    重写与重载的含义
    抽象类和接口的区别
    Spring知识点
    mybatis学习
    知识点
    Mybatis面试题
  • 原文地址:https://www.cnblogs.com/yigexigua/p/3909779.html
Copyright © 2011-2022 走看看