• [BZOJ2595][WC2008] 游览计划


    [BZOJ2595][WC2008] 游览计划

    link

    试题分析

    斯坦纳树裸题。
    什么是斯坦纳树呢?就是求一类生成树,用如下dp方程即可求解:
    (f_{i,j})表示点(i)与其它的关键点连通性为(j)的最小花费。

    [f_{i,j}=f_{i,s}+f_{i,joplus s} (sin j) ]

    [f_{i,j}=f_{k,j}+Cost_{i,k} ]

    不难发现,如果把两维独立的话,那么上面就是层之间的转移。
    下面就是一个层之内的松弛操作,用最短路松弛即可解决。

     
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<algorithm>
     
    using namespace std;
    #define LL long long
     
    inline int read(){
        int x=0,f=1; char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int INF = 1007483600;
    const int MAXN = 100010;
     
    int N,M; struct Mx{int x,y; Mx(int xx=0,int yy=0){x=xx; y=yy;}}; queue<Mx> que; 
    struct Pos{int x,y,Grz; Pos (int xx=0,int yy=0,int Grzz=0){x=xx; y=yy; Grz=Grzz;} };
    int f[11][11][(1<<11)];Pos g[11][11][(1<<11)]; bool vis[11][11];
    int dis[4][2]={{0,-1},{-1,0},{0,1},{1,0}}; int a[11][11];
     
    inline void SPFA(int t){
        while(!que.empty()){
            Mx k=que.front(); que.pop(); vis[k.x][k.y]=false;
            for(int i=0;i<4;i++){
                int xx=k.x+dis[i][0],yy=k.y+dis[i][1];
                if(xx<1||xx>N||yy<1||yy>M) continue;
                if(f[xx][yy][t]>f[k.x][k.y][t]+a[xx][yy]){
                    f[xx][yy][t]=f[k.x][k.y][t]+a[xx][yy];
                    g[xx][yy][t]=Pos(k.x,k.y,t);
                    if(!vis[xx][yy]) vis[xx][yy]=true,que.push(Mx(xx,yy));
                }
            }
        } return ;
    }
    inline void dfs(int x,int y,int t){
        if(!x||!y||!t) return ; vis[x][y]=true;
        dfs(g[x][y][t].x,g[x][y][t].y,g[x][y][t].Grz);
        if(g[x][y][t].x==x&&g[x][y][t].y==y) 
            dfs(g[x][y][t].x,g[x][y][t].y,t-g[x][y][t].Grz);
    }
    int x[11],y[11],C;
     
    int main(){
        //freopen(".in","r",stdin);
        //freopen(".out","w",stdout);
        N=read(),M=read();
        for(int i=1;i<=N;i++){
            for(int j=1;j<=M;j++) {
                a[i][j]=read();
                if(!a[i][j]) x[++C]=i,y[C]=j;
            }
        } for(int i=0;i<=N;i++){
            for(int j=0;j<=M;j++)
                for(int k=0;k<(1<<C);k++) f[i][j][k]=INF;
        }
        for(int i=1;i<=C;i++) f[x[i]][y[i]][(1<<(i-1))]=0;
        for(int Grz=1;Grz<(1<<C);Grz++){
            for(int i=1;i<=N;i++){
                for(int j=1;j<=M;j++){
                    for(int k=Grz;k;k=(k-1)&Grz){
                        if(f[i][j][Grz]>f[i][j][Grz^k]+f[i][j][k]-a[i][j]){
                            f[i][j][Grz]=f[i][j][Grz^k]+f[i][j][k]-a[i][j];
                            g[i][j][Grz]=Pos(i,j,k);
                        }
                    } if(f[i][j][Grz]<INF) que.push(Mx(i,j)),vis[i][j]=true;
                }
            } SPFA(Grz);
        } printf("%d
    ",f[x[1]][y[1]][(1<<C)-1]);
        memset(vis,false,sizeof(vis)); dfs(x[1],y[1],(1<<C)-1);
        for(int i=1;i<=N;i++){
            for(int j=1;j<=M;j++){
                if(!a[i][j]) putchar('x');
                else if(vis[i][j]) putchar('o');
                else putchar('_');
            } puts("");
        }
        return 0;
    }
    
  • 相关阅读:
    LeetCode Algorithm
    实现QObject与JavaScript通讯(基于QWebEngine + QWebChannel)
    Linux工具参考篇(网摘)
    GO 语言简介(网摘)
    Qt窗体引用window自带阴影边框效果
    无插件VIM编程技巧(网摘)
    ASP.NET 5基础之中间件
    ASP.NET Core 1.0基础之应用启动
    理解ASP.NET 5 Web Apps
    DNX 概览
  • 原文地址:https://www.cnblogs.com/wxjor/p/9515727.html
Copyright © 2020-2023  润新知