AC日记——[Wc2008]游览计划 bzoj 2595

2595

 

思路:

  状压DP+spfa转移+dfs输出路径;

  或者,斯坦纳树算法模板;

 

来,上代码:

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
 
using namespace std;
 
#define INF 0x7ffffff
 
struct NodeType {
    int x,y,s;
};
struct NodeType pre[15][15][10005];
 
const int dx[5]={0,-1,0,1,0};
const int dy[5]={0,0,1,0,-1};
 
int n,m,map[15][15],num,bi[15],all,dp[15][15][10005],ans;
 
bool if_[15][15],cho[15][15];
 
queue<NodeType>que;
 
inline void in(int &now)
{
    char Cget=getchar();now=0;
    while(Cget>'9'||Cget<'0') Cget=getchar();
    while(Cget>='0'&&Cget<='9')
    {
        now=now*10+Cget-'0';
        Cget=getchar();
    }
}
 
void read()
{
    in(n),in(m),bi[0]=1;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            in(map[i][j]);
            if(!map[i][j]) num++;
        }
    }
    for(int i=1;i<=num;i++) bi[i]=bi[i-1]<<1;
    all=bi[num]-1;
}
 
void spfa(int f)
{
    while(!que.empty())
    {
        NodeType now=que.front();que.pop(),if_[now.x][now.y]=false;
        for(int i=1;i<=4;i++)
        {
            int x=now.x+dx[i],y=now.y+dy[i];
            if(x>0&&x<=n&&y>0&&y<=m)
            {
                if(dp[x][y][f]>dp[now.x][now.y][f]+map[x][y])
                {
                    dp[x][y][f]=dp[now.x][now.y][f]+map[x][y];
                    pre[x][y][f]=(NodeType){now.x,now.y,now.s};
                    if(!if_[x][y]) que.push((NodeType){x,y,f}),if_[x][y]=true;
                }
            }
        }
    }
}

void dfs(int x,int y,int s)
{
    if(x>INF||pre[x][y][s].s==0) return ;
    cho[x][y]=true;
    dfs(pre[x][y][s].x,pre[x][y][s].y,pre[x][y][s].s);
    if(x==pre[x][y][s].x&&y==pre[x][y][s].y) dfs(x,y,s-pre[x][y][s].s);
}

void solve()
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            for(int v=1;v<=all;v++) dp[i][j][v]=INF;
        }
    }
    int F=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(!map[i][j]) dp[i][j][bi[F++]]=0;
        }
    }
    for(int S=1;S<=all;S++)
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                for(int s=S&(S-1);s;s=S&(s-1))
                {
                    int tmp=dp[i][j][s]+dp[i][j][S-s]-map[i][j];
                    if(tmp<dp[i][j][S])
                    {
                        dp[i][j][S]=tmp;
                        pre[i][j][S]=(NodeType){i,j,s};
                    }
                }
                if(dp[i][j][S]<INF) que.push((NodeType){i,j,S}),if_[i][j]=true;
            }
        }
        spfa(S);
    }
    int ex,ey;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(!map[i][j])
            {
                ex=i,ey=j,ans=dp[i][j][all];
                break;
            }
        }
    }
    dfs(ex,ey,all);
}

void print()
{
    printf("%d\n",ans);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(!map[i][j]) putchar('x');
            else if(cho[i][j]) putchar('o');
            else putchar('_');
        }
        putchar('\n');
    }
}

int main()
{
    read();
    solve();
    print();
    return 0;
}

 

posted @ 2017-05-05 16:09  IIIIIIIIIU  阅读(175)  评论(0编辑  收藏  举报