• BZOJ2595 WC2008游览计划(斯坦纳树)


      斯坦纳树板子题。

      考虑状压dp,设f[i][j][S]表示当前在点(i,j)考虑转移,其所在的联通块包含的关键点集(至少)为S的答案。

      转移时首先枚举子集,有f[i][j][S]=min{f[i][j][x]+f[i][j][y]-a[i][j]} (x&y=0,x|y=S)。

      然后考虑从点(i,j)从哪拓展而来,有f[i][j][S]=min{f[x][y][S]}+a[i][j],其中(x,y)为(i,j)的相邻点,使用spfa转移。

      这里第二种转移仅在相同关键点集下进行,因为由更小点集转移而来的情况已在第一种转移中被考虑。

      对于输出方案,记录如何转移而来即可。

      其实并没有搞懂。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 12
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int n,m,s,a[N][N],id[N][N],f[N][N][1<<N],from[N][N][1<<N][2],q[N*N*N*N][2];
    int wx[4]={1,0,0,-1},wy[4]={0,1,-1,0};
    bool flag[N][N];
    char b[N][N];
    void inc(int &x){x++;if (x>n*m+1) x-=n*m+1;}
    void spfa(int k)
    {
        int head=0,tail=0;
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++)
            tail++,q[tail][0]=i,q[tail][1]=j,flag[i][j]=1;
        do
        {
            inc(head);int x=q[head][0],y=q[head][1];flag[x][y]=0;
            for (int i=0;i<4;i++)
            {
                int u=x+wx[i],v=y+wy[i];
                if (u&&u<=n&&v&&v<=m&&f[x][y][k]+a[u][v]<f[u][v][k])
                {    
                    f[u][v][k]=f[x][y][k]+a[u][v];
                    from[u][v][k][0]=x,from[u][v][k][1]=y;
                    if (!flag[u][v]) flag[u][v]=1,inc(tail),q[tail][0]=u,q[tail][1]=v;
                }
            }
        }while (head!=tail);
    }
    void getans(int x,int y,int k)
    {
        b[x][y]='o';
        while (from[x][y][k][0]>0)
        {
            int u=from[x][y][k][0],v=from[x][y][k][1];
            b[x=u][y=v]='o';
        }
        if (from[x][y][k][0]<0) getans(x,y,-from[x][y][k][0]),getans(x,y,-from[x][y][k][1]);
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj2595.in","r",stdin);
        freopen("bzoj2595.out","w",stdout);
    #endif
        n=read(),m=read();
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++)
            {
                a[i][j]=read(),s+=(a[i][j]==0);
                if (!a[i][j]) id[i][j]=s;
            }
        memset(f,42,sizeof(f));
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++)
            {
                f[i][j][0]=a[i][j];
                if (id[i][j]) f[i][j][1<<id[i][j]-1]=a[i][j];
            }
        for (int k=1;k<(1<<s);k++)
        {
            for (int i=1;i<=n;i++)
                for (int j=1;j<=m;j++)
                    for (int x=k;x>=(k^x);x=x-1&k)
                    if (f[i][j][x]+f[i][j][k^x]-a[i][j]<f[i][j][k])
                    {
                        f[i][j][k]=f[i][j][x]+f[i][j][k^x]-a[i][j];
                        from[i][j][k][0]=-x,from[i][j][k][1]=-(k^x);
                    }
            spfa(k);
        }
        int ans=100000000;
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++)
            ans=min(ans,f[i][j][(1<<s)-1]);
        cout<<ans<<endl;
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++)
            b[i][j]='_';
        for (int i=1;i<=n;i++)
            for (int j=1;j<=m;j++)
            if (f[i][j][(1<<s)-1]==ans)
            {
                getans(i,j,(1<<s)-1);
                for (int i=1;i<=n;i++)
                    for (int j=1;j<=m;j++)
                    if (!a[i][j]) b[i][j]='x';
                for (int i=1;i<=n;i++)
                {
                    for (int j=1;j<=m;j++)
                    putchar(b[i][j]);
                    cout<<endl;
                }
                return 0;
            }
    }
  • 相关阅读:
    04-树7 二叉搜索树的操作集
    04-树6 Complete Binary Search Tree
    04-树5 Root of AVL Tree
    04-树4 是否同一棵二叉搜索树
    05-树8 File Transfer
    05-树7 堆中的路径
    二叉树的非递归遍历(先序、中序、后序和层序遍历)
    队列的定义与操作——顺序存储和链式存储
    Maven项目的核心pom.xml解释(转)
    eclipse安装插件的三种方式
  • 原文地址:https://www.cnblogs.com/Gloid/p/10256845.html
Copyright © 2020-2023  润新知