zoukankan      html  css  js  c++  java
  • 【BZOJ2595】 [Wc2008]游览计划

    BZOJ2595 [Wc2008]游览计划


    Solution

    考虑这是一个最小费用连通性的问题,既然大家都说这是什么斯坦纳树那就是的吧...

    所以我们肯定可以这样设一个dp状态:

    (dp_{i,j,k})表示经过点(i,j)且现在连通性为(k)的最小费用.

    有两种转移方程:

    1. (dp_{i,j,k}=dp_{i,j,s}+dp_{i,j,k-s}-a[i][j];)

    2. (dp_{i,j,k}=dp_{x,y,k}+a[i][j])

    这个还是比较显然?

    发现后面那个东西很像最短路不是吗?

    直接SPFA+dp转移一下就好了.

    代码实现

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<map>
    #include<iostream>
    using namespace std;
    #define ll long long
    #define re register
    #define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
    inline int gi()
    {
        int f=1,sum=0;char ch=getchar();
        while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
        return f*sum;
    }
    const int N=20,Inf=1e9;
    int bin[N],f[12][12][1024],vis[N][N];
    int wa[4]={1,0,-1,0};
    int lk[4]={0,1,0,-1};
    struct node{
        int a,b,c;
    }pre[12][12][60010];
    int a[N][N],n,m,b[N][N];
    typedef pair<int,int> pii;
    #define mp make_pair
    queue<pii>Q;
    void spfa(int s){
        while(!Q.empty()){
            pii now=Q.front();Q.pop();
            int x=now.first,y=now.second;vis[x][y]=0;
            for(int i=0;i<4;i++){
                int xx=x+wa[i],yy=y+lk[i];
                if(xx<1 || xx>n || yy<1 || yy>m)continue;
                if(f[xx][yy][s]>f[x][y][s]+a[xx][yy]){
                    f[xx][yy][s]=f[x][y][s]+a[xx][yy];
                    pre[xx][yy][s]=(node){x,y,s};
                    if(!vis[xx][yy]){
                        vis[xx][yy]=1;Q.push(mp(xx,yy));
                    }
                }
            }
        }
    }
    void dfs(int i,int j,int s)
    {
        if(i>=Inf || pre[i][j][s].c==0)return;
        b[i][j]=1;node q=pre[i][j][s];
        dfs(q.a,q.b,q.c);
        if(q.a==i && q.b==j)dfs(i,j,s-q.c);
    }
    int main()
    {
        int K=0;
        bin[0]=1;for(int i=1;i<20;i++)bin[i]=bin[i-1]<<1;
        n=gi();m=gi();
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                a[i][j]=gi();
                if(!a[i][j])K++;
            }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                for(int k=0;k<bin[K];k++)
                    f[i][j][k]=pre[i][j][k].a=Inf;
        K=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(!a[i][j])
                    f[i][j][bin[K]]=0,K++;
        for(int s=1;s<bin[K];s++){
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++){
                    for(int ss=s&(s-1);ss;ss=s&(ss-1)){
                        int t=f[i][j][ss]+f[i][j][s-ss]-a[i][j];
                        if(t<f[i][j][s]){
                            f[i][j][s]=t;pre[i][j][s]=(node){i,j,ss};
                        }
                    }
                    if(f[i][j][s]<Inf){
                        Q.push(mp(i,j));vis[i][j]=1;
                    }
                }
            spfa(s);
        }
        int x=0,y;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++)
                if(!a[i][j]){
                    x=i;y=j;break;
                }
            if(x)break;
        }
        dfs(x,y,bin[K]-1);
        printf("%d
    ",f[x][y][bin[K]-1]);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++)
                if(!a[i][j])putchar('x');
                else if(b[i][j])putchar('o');
                else putchar('_');
            putchar('
    ');
        }
        return 0;
    }
    
  • 相关阅读:
    Pycharm简单使用教程
    【Jenkins学习】【第二节】 jenkins构建触发器定时任务
    Docker之从零开始制作docker镜像
    手机APP自动化环境搭建
    格式字符详解
    Bash Shell之内建命令和保留字
    asp.net 实现后台异步处理的方式
    Spring3.2.0 之后各个版本完整包下载地址
    Oracle的rollup、cube、grouping sets函数
    C# 委托类型及使用
  • 原文地址:https://www.cnblogs.com/mleautomaton/p/10312764.html
Copyright © 2011-2022 走看看