洛谷 P4294 [WC2008]游览计划

题目链接

不是很会呢,但似乎抄了题解后有点明白了

sol:状态DP显然,其实是要构建一棵最小生成树一样的东西,我自己的理解(可能不是很对哦希望多多指教)f[x][y][zt]就是到x,y这个点,状态为zt,时的最小代价于是有两种转移方法:一种是若zt1|zt2=zt且zt1&zt2==0,那么f[x][y][zt]=min(f[x][y][zt],f[x][y][zt1]+f[x][y][zt2]),第二种就是跑spfa,如x1,y1和x,y联通,f[x1][y1][zt''']=min(f[x1][y1][zt'''],f[x][y][zt]+v[x1][y1])  看起来不是很难,实现起来对菜鸡来说可费劲了qaq

#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=12,B=(1<<11),inf=1e7,dx[]={-1,1,0,0},dy[]={0,0,-1,1};
int n,m,f[N][N][B],v[N][N],tot=0,SX,SY,inq[N][N],re[N][N];
queue<pair<int,int> >q;
struct node
{
    int x,y,zt;
}pre[N][N][B];
inline void spfa(int zt)
{
    int i,xx,yy; pair<int,int>pp;
    while(!q.empty())
    {
        pp=q.front(); q.pop(); inq[pp.first][pp.second]=0;
        for(i=0;i<4;i++)
        {
            xx=pp.first+dx[i]; yy=pp.second+dy[i]; if(xx<1||xx>n||yy<1||yy>m)continue;
            if(f[xx][yy][zt]>f[pp.first][pp.second][zt]+v[xx][yy])
            {
                f[xx][yy][zt]=f[pp.first][pp.second][zt]+v[xx][yy]; pre[xx][yy][zt]=(node){pp.first,pp.second,zt};
                if(!inq[xx][yy]) q.push(make_pair(xx,yy)),inq[xx][yy]=1;
            }
        }
    }
}
inline void dfs(int x,int y,int zt)
{
    if(!pre[x][y][zt].zt)return; re[x][y]=1;
    node tmp=pre[x][y][zt]; dfs(tmp.x,tmp.y,tmp.zt); if(tmp.x==x&&tmp.y==y)dfs(x,y,zt^tmp.zt);
}
int main()
{
    int i,j,zt,zz; scanf("%d%d",&n,&m); memset(f,63,sizeof f);
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=m;j++)
        {
            scanf("%d",&v[i][j]); if(!v[i][j]) f[i][j][1<<tot]=0,SX=i,SY=j,tot++;
        }
    }
    for(zt=0;zt<(1<<tot);zt++)
    {
        while(!q.empty()) q.pop(); memset(inq,0,sizeof inq);
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            {
                for(zz=zt;zz;zz=zt&(zz-1))
                {
                    if(f[i][j][zt]>f[i][j][zz]+f[i][j][zt^zz]-v[i][j])
                    {
                        f[i][j][zt]=f[i][j][zz]+f[i][j][zt^zz]-v[i][j]; pre[i][j][zt]=(node){i,j,zz};
                    }
                }if(f[i][j][zt]<inf) q.push(make_pair(i,j)),inq[i][j]=1;
            }
        }spfa(zt);
    }printf("%d\n",f[SX][SY][(1<<tot)-1]); dfs(SX,SY,(1<<tot)-1);
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=m;j++)
        {
            if(!v[i][j])putchar('x');else if(re[i][j])putchar('o');else putchar('_');
        }puts("");
    }return 0;
}

猜你喜欢

转载自www.cnblogs.com/gaojunonly1/p/9738723.html