• bzoj4006: [JLOI2015]管道连接


    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4006

    思路:

    一眼看上去很像斯坦纳树

    但是限制稍有不同,只要每种颜色的点联通即可

    也就是说最后可能是森林

    我听说裸写斯坦纳树有90


    所以我们要在外面再套一层DP

    f[i][j]还是斯坦纳树的状态,i是以i为根,j是状态为j

    先用斯坦纳树求出每种联通状况的最小费用

    再设dp[i]表示i这个状态的最小费用

    枚举子集时保证颜色相同的连通性相同,转移即可

    dp[i]=min(dp[j]+dp[i-j])j是i的子集

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    const int maxn=11,maxk=11,maxq=105;
    const int dx[]={0,0,1,-1},dy[]={1,-1,0,0};
    using namespace std;
    int n,m,K,head,tail,cnt,pw[maxk+5],w[maxk],q[maxq+10],f[maxn][maxn][1<<maxk],pre[maxn][maxn][1<<maxk],a[maxn][maxn],inf;
    bool bo[maxn][maxn],vis[maxn][maxn];
    inline bool in(int x,int y){return x>=0&&x<n&&y>=0&&y<m;}
    inline int id(int x,int y){return x*10+y;}
    inline int id2(int x,int y,int s){return s*100+x*10+y;}
    inline void decode(int sta,int &x,int &y){x=sta/10,y=sta%10;}
    inline void decode2(int sta,int &x,int &y,int &s){s=sta/100,x=sta%100/10,y=sta%10;}
     
    void init(){
        pw[0]=1;for (int i=1;i<=11;i++) pw[i]=pw[i-1]<<1;
        scanf("%d%d",&n,&m);
        for (int i=0;i<n;i++)
            for (int j=0;j<m;j++){
                scanf("%d",&a[i][j]);
                if (!a[i][j]) w[K++]=id(i,j);
            }
    }
     
    void spfa(int s){
        //printf("s=%d
    ",s);
        while (head!=tail){
            if (++head>maxq) head=1;
            int sta=q[head],x,y;
            decode(sta,x,y);
            //printf("x=%d y=%d
    ",x,y);
            for (int i=0;i<4;i++){
                int nx=x+dx[i],ny=y+dy[i];
                if (!in(nx,ny)) continue;//printf("nx=%d ny=%d
    ",nx,ny);
                if (f[nx][ny][s]>f[x][y][s]+a[nx][ny]){
                    f[nx][ny][s]=f[x][y][s]+a[nx][ny];
                    //printf("ffffffffffffffffffffffffffffff=%d
    ",f[nx][ny][s]);
                    pre[nx][ny][s]=id2(x,y,s);
                    if (!bo[nx][ny]){
                        if (++tail>maxq) tail=1;
                        bo[nx][ny]=1,q[tail]=id(nx,ny);
                    }
                }
            }
            bo[x][y]=0;
        }
    }
     
    void dfs(int i,int s){
        int x,y,nx,ny,t;
        decode(i,x,y);
        //printf("x=%d y=%d s=%d
    ",x,y,s);
        vis[x][y]=1;
         
        if (!pre[x][y][s]) return;
        //printf("%d %d
    ",id2(x,y,s),pre[x][y][s]);
        decode2(pre[x][y][s],nx,ny,t);
        //printf("px=%d py=%d pt=%d
    ",nx,ny,t);
        dfs(id(nx,ny),t);
        if (x==nx&&y==ny) dfs(id(nx,ny),s^t);
    }
     
    void work(){
        memset(f,63,sizeof(f)),inf=f[0][0][0];
        for (int i=0,x,y;i<K;i++){
            decode(w[i],x,y);
            f[x][y][pw[i]]=0;
        }
        for (int sta=1;sta<pw[K];sta++){
            head=tail=0;
            for (int i=0;i<n;i++)
                for (int j=0;j<m;j++){
                    for (int s=sta&(sta-1);s;s=(s-1)&sta)
                        if (f[i][j][sta]>f[i][j][s]+f[i][j][sta^s]-a[i][j]){
                            f[i][j][sta]=f[i][j][s]+f[i][j][sta^s]-a[i][j];
                            pre[i][j][sta]=id2(i,j,s);
                        }
                    if (f[i][j][sta]!=inf) q[++tail]=id(i,j),bo[i][j]=1;//printf("x=%d y=%d sta=%d f=%d
    ",i,j,sta,f[i][j][sta]);
                }
            spfa(sta);
        }
        int x,y;
        decode(w[0],x,y);
        //printf("xx=%d yy=%d sta=%d
    ",x,y,pw[K]-1);
        printf("%d
    ",f[x][y][pw[K]-1]);
        int nx,ny,ns;
        decode2(pre[x][y][pw[K]-1],nx,ny,ns);
        //printf("nx=%d ny=%d ns=%d
    ",nx,ny,ns);
        dfs(w[0],pw[K]-1);
        for (int i=0;i<n;i++,puts(""))
            for (int j=0;j<m;j++)
                if (!a[i][j]) putchar('x');
                else if (vis[i][j]) putchar('o');
                else putchar('_');
    }
     
    int main(){
        //freopen("test.in","r",stdin);freopen("test.out","w",stdout);
        init(),work();
        return 0;
    }
    /*
    8 8
    1 4 1 3 4 2 4 1
    4 3 1 2 0 1 2 3
    3 2 1 3 0 3 1 2
    2 6 5 0 2 4 1 0
    5 1 2 1 3 4 2 5
    5 1 3 1 5 0 1 4
    5 0 6 1 4 5 3 4
    0 2 2 2 3 4 1 1
     
    */


  • 相关阅读:
    Android中Handler的使用
    Android ListView使用
    Android ListView的XML属性
    Android ListView几个重要属性
    Android设置日期DatePickerDialog
    Android资源文件说明
    Android使用xml文件中的array资源
    Android:控件Spinner实现下拉列表
    如何搭建个人博客网站(Mac)
    SVProgressHUD源码解读(2.0.3)
  • 原文地址:https://www.cnblogs.com/thythy/p/5493626.html
Copyright © 2020-2023  润新知