• 洛谷 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
    ",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;
    }
  • 相关阅读:
    制作一个螺旋矩阵
    通过C++修改系统时间代码
    绝对值最小
    compile cmdow
    2017-10-04清北模拟赛
    2017-10-03清北模拟赛
    2017-10-01清北模拟赛
    HTML容易遗忘内容(二)
    SSM框架关于后台返回JSON数据中显示很多不需要的字段为NULL
    关于Unix时间戳转北京时间的问题
  • 原文地址:https://www.cnblogs.com/gaojunonly1/p/9738723.html
Copyright © 2020-2023  润新知