码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 2595 游览计划(插头DP)

时间:2014-06-23 08:02:51      阅读:317      评论:0      收藏:0      [点我收藏+]

标签:style   class   blog   code   http   tar   

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2595

题意:给出一个数字矩阵。求一个连通块包含所有的数字0且连通块内所有数字之和最小。

思路:对于每个格子,是0则必须要选。那么对于不选的格子(i,j)在什么时候可以不选呢?必须同时满足以下两个条件:

(1)(i,j)不是0;

(2)(i-1,j)不选或者(i-1,j)选了但是轮廓线上还有别的地方与(i-1,j)是一个连通块。

 

int Pre[105][N],op[105][N];


struct node
{
    int head[mod],next[N],e,st[N],val[N];
    
    void init()
    {
        clr(head,-1); e=0;
    }
    
    void add(int S,int K,int preSt,int flag,int t)
    {
        int x=S%mod;
        int i;
        for(i=head[x];i!=-1;i=next[i])
        {
            if(st[i]==S) 
            {
                if(K<val[i]) 
                {
                    val[i]=K;
                    Pre[t][i]=preSt;
                    op[t][i]=flag;
                }
                return;
            }
        }
        Pre[t][e]=preSt;
        op[t][e]=flag;
        
        st[e]=S; val[e]=K; next[e]=head[x]; 
        head[x]=e++;
    }
};


node f[2];
int pre,cur,a[15][15],n,m;
int S[15];




void decode(int st)
{
    int i;
    for(i=0;i<m;i++) S[i]=st&7,st>>=3;
}


int incode()
{
    int x=0,i,t=1;
    int mp[8];
    FOR0(i,8) mp[i]=-1;
    mp[0]=0;
    for(i=m-1;i>=0;i--)
    {
        if(mp[S[i]]==-1) mp[S[i]]=t++;
        S[i]=mp[S[i]];
        x=(x<<3)|S[i];
    }
    return x;
}


void tran(int x,int y)
{
    int i;
    for(i=0;i<m;i++) if(S[i]==y) S[i]=x;
}


void DP(int i,int j,int flag)
{
    int x,y,k,t,st,cost,r=i*m+j;
    int num,temp;
    for(k=0;k<f[pre].e;k++)
    {
        st=f[pre].st[k];
        cost=f[pre].val[k];
        
        decode(st);
        x=j==0?0:S[j-1]; 
        y=i==0?0:S[j]; 
        
        if(!flag)
        {
            num=0;
            FOR0(t,m) if(S[t]==y) num++;
            if(S[j]==0||num>1) 
            {
                temp=S[j]; S[j]=0;
                f[cur].add(incode(),cost,k,0,r);
                S[j]=temp;
            }
        }
        
        if(x&&y) tran(x,y);
        else if(x||y) S[j]=x+y;
        else S[j]=7;
        f[cur].add(incode(),cost+a[i][j],k,1,r);
    }
}


char str[15][15];


void DFS(int k,int x)
{
    int i=x/m,j=x%m;
    if(op[x][k]) str[i][j]=a[i][j]?‘o‘:‘x‘;
    else str[i][j]=‘_‘;
    if(x<0) return;
    DFS(Pre[x][k],x-1);
}


int main()
{
    RD(n,m);
    int i,j;
    FOR0(i,n) FOR0(j,m) RD(a[i][j]);
    pre=0; cur=1;
    f[pre].init(); f[pre].add(0,0,0,0,0);
    FOR0(i,n) FOR0(j,m)
    {
        f[cur].init();
        if(a[i][j]) DP(i,j,0);
        else DP(i,j,1);
        swap(cur,pre);
    }
    int ans=INF,last;
    FOR0(i,f[pre].e)
    {
        decode(f[pre].st[i]);
        FOR0(j,m) if(S[j]>1) break; 
        if(j>=m&&f[pre].val[i]<ans) 
        {
            ans=f[pre].val[i];
            last=i;
        }
    }
    PR(ans); DFS(last,n*m-1);
    FOR0(i,n) str[i][m]=0,puts(str[i]);
}

 

 

 

BZOJ 2595 游览计划(插头DP),布布扣,bubuko.com

BZOJ 2595 游览计划(插头DP)

标签:style   class   blog   code   http   tar   

原文地址:http://www.cnblogs.com/jianglangcaijin/p/3799505.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!