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;
}

 

posted on 2014-08-13 12:24  一个西瓜  阅读(148)  评论(0编辑  收藏  举报

导航