zoukankan      html  css  js  c++  java
  • 【BZOJ2595】[WC2008] 游览计划(斯坦纳树入门)

    点此看题面

    大致题意: 给定一个(n imes m)的网格图,其中有(k)个必选点,而选择其他点都有一个代价。要求选出一个连通块,使得包含所有必选点,且总代价最小。

    斯坦纳树

    可见这篇博客:斯坦纳树入门小记

    输出方案

    这题作为斯坦纳树的板子,除一般的斯坦纳树以外,唯一要注意的就是方案的输出了。

    我们只需在(DP)过程中记录下每个状态的前驱状态,然后从后往前(dfs)一遍即可。

    注意根据点转移有两个前驱状态,但实际存储时只需记录一个就行了,具体实现详见代码。

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 10
    #define P(x,y) (((x)-1)*m+(y))
    #define fi(x) (((x)-1)/m+1)
    #define se(x) (((x)-1)%m+1)
    #define INF f[0][0]
    using namespace std;
    const int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
    int n,m,k,a[N*N+5],f[N*N+5][1<<N],gx[N*N+5][1<<N],gs[N*N+5][1<<N];char ans[N+5][N+5];
    int IQ[N*N+5];queue<int> q;I void SPFA(CI s)//SPFA优化转移
    {
    	RI i,k,x,y,nk,nx,ny;W(!q.empty())
    	{
    		for(IQ[k=q.front()]=0,q.pop(),x=fi(k),y=se(k),i=0;i^4;++i)
    			(nx=x+dx[i])&&nx<=n&&(ny=y+dy[i])&&ny<=m&&(nk=P(nx,ny),f[nk][s]>f[k][s]+a[nk])&&
    			(f[nk][s]=f[k][s]+a[nk],gx[nk][s]=k,gs[nk][s]=s,!IQ[nk]&&(q.push(nk),IQ[nk]=1));
    	}
    }
    I void Draw(CI i,CI j)//从后往前DFS得到方案
    {
    	i&&(a[i]&&(ans[fi(i)][se(i)]='o'),gx[i][j]==i&&(Draw(i,j^gs[i][j]),0),Draw(gx[i][j],gs[i][j]),0);//注意根据点转移的两种状态
    }
    int main()
    {
    	RI i,j,rt;for(memset(f,63,sizeof(f)),scanf("%d%d",&n,&m),i=1;i<=n*m;++i)//读入数据
    		scanf("%d",a+i),ans[fi(i)][se(i)]=a[i]?'_':'x',!a[i]&&(++k,f[rt=i][1<<k-1]=0);
    	for(RI s=0,l=1<<k,x,y;s^l;++s)//枚举子集
    	{
    		for(i=1;i<=n*m;++i) for(j=s;j;j=(j-1)&s)//枚举作为根的点,根据点转移
    			f[i][s]>f[i][j]+f[i][s^j]-a[i]&&(f[i][s]=f[i][j]+f[i][s^j]-a[i],gx[i][s]=i,gs[i][s]=j);
    		for(i=1;i<=n*m;++i) f[i][s]^INF&&(q.push(i),IQ[i]=1);SPFA(s);//把有效点加入队列,根据边转移
    	}
    	for(printf("%d
    ",f[rt][(1<<k)-1]),Draw(rt,(1<<k)-1),i=1;i<=n;++i) puts(ans[i]+1);return 0;//输出答案
    }
    
  • 相关阅读:
    if语句
    操作列表
    列表
    数据类型(不全)
    windows安装mysql
    hadr启动报错码
    db2主备hadr部署
    java--遍历字符个数
    java--装饰类
    java--继承&接口
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ2595.html
Copyright © 2011-2022 走看看