luoguP4294 [WC2008]游览计划 斯坦纳树

这个其实就是状压DP+spfa.    

本题需要输出方案,有一点点麻烦 

code:   

#include <bits/stdc++.h>     
#define ll long long 
#define N 12     
#define inf 0x3f3f3f3f
#define setIO(s) freopen(s".in","r",stdin)  
using namespace std;      
int dx[]={0,-1,0,1};   
int dy[]={-1,0,1,0};          
int n,m,K=0,tot;    
int val[N][N];   
int bin[N],f[N*N][1<<N],id[N][N],X[N*N],Y[N*N],v[N*N],inq[N*N];              
struct node 
{
    int pos,s;   
    node(int pos=0,int s=0):pos(pos),s(s){}  
}pre[N*N][1<<N];        
queue<int>q;      
void solve(int cur) 
{
    while(!q.empty()) 
    {
        int u=q.front(); 
        q.pop(),inq[u]=0;   
        int x=X[u],y=Y[u];    
        for(int i=0;i<4;++i) 
        {
            int xx=x+dx[i]; 
            int yy=y+dy[i]; 
            if(!(xx>=1&&xx<=n&&yy>=1&&yy<=m)) 
                continue;      
            int to=id[xx][yy];    
            if(f[to][cur]>f[u][cur]+v[to]) 
            {
                f[to][cur]=f[u][cur]+v[to];        
                pre[to][cur]=node(u,cur);      
                if(!inq[to]) 
                {
                    inq[to]=1;     
                    q.push(to);     
                }
            }
        }
    }
}     
int mk[N][N];   
void dfs(int x,int now) 
{    
    mk[X[x]][Y[x]]=1;    
    if(!pre[x][now].pos)   
        return;     
    if(pre[x][now].pos==x)   
        dfs(x,now^pre[x][now].s);    
    dfs(pre[x][now].pos,pre[x][now].s);   
}
int main() 
{ 
    // setIO("input");     
    int i,j,rr=0;     
    scanf("%d%d",&n,&m);   
    for(i=1;i<N;++i)  
        bin[i]=1<<(i-1);     
    for(i=1;i<=n;++i)   
        for(j=1;j<=m;++j)  
            id[i][j]=++tot,X[id[i][j]]=i,Y[id[i][j]]=j;     
    memset(f,0x3f,sizeof(f));      
    for(i=1;i<=n;++i)   
        for(j=1;j<=m;++j)   
        {
            scanf("%d",&val[i][j]);      
            v[id[i][j]]=val[i][j];  
            if(!val[i][j])    
            {
                ++K;      
                rr=id[i][j];                  
                f[id[i][j]][bin[K]]=0;  
            }    
        }
    for(i=1;i<bin[K+1];++i) 
    {                       
        for(int pos=1;pos<=tot;++pos)     
        {
            for(j=i&(i-1);j;j=i&(j-1)) 
            {
                if(f[pos][j]+f[pos][i^j]-v[pos]<f[pos][i]) 
                {  
                    f[pos][i]=f[pos][j]+f[pos][i^j]-v[pos];    
                    pre[pos][i]=node(pos,j);         
                }   
            }      
            if(f[pos][i]<inf)   
            {     
                inq[pos]=1;   
                q.push(pos);    
            }
        }         
        solve(i);    
    }
    printf("%d\n",f[rr][bin[K+1]-1]); 
    dfs(rr,bin[K+1]-1);   
    for(i=1;i<=n;++i) 
    {
        for(j=1;j<=m;++j)   
        {
            if(!val[i][j])   
            { 
                printf("x");     
            }
            else 
            { 
                if(mk[i][j])   printf("o");       
                else printf("_"); 

            }
        }
        printf("\n"); 
    }      
    return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/guangheli/p/12482114.html