WC2008 浏览计划

来源:互联网 发布:matlab 把矩阵归一化 编辑:程序博客网 时间:2024/04/30 07:11

斯坦纳树

#include<cstdio>#include<cstring>#include<queue>#define N 11#define M 1100#define INF 100000000using namespace std;int n,m,k,K;int st[N][N];int dp[N][N][M];int pre[N][N][M];bool vis[N][N][M],ok[N][N];int map[N][N];queue<int>q;int h[]={1,-1,0,0};int g[]={0,0,-1,1};void init(){    int i,j,p;    k=0;    memset(st,0,sizeof(st));    memset(vis,0,sizeof(vis));    memset(pre,0,sizeof(pre));    for(i=0;i<n;i++){        for(j=0;j<m;j++){            scanf("%d",&map[i][j]);            if(map[i][j]==0)                st[i][j]=(1<<(k++));        }    }    K=(1<<k);    for(i=0;i<n;i++)        for(j=0;j<m;j++){            for(p=0;p<K;p++)                dp[i][j][p]=INF;            if(st[i][j])                dp[i][j][st[i][j]]=0;        }}void SPFA(){    int i;    while(!q.empty()){        int x=q.front()/1000000,y=(q.front()-x*1000000)/10000,z=q.front()%10000;        vis[x][y][z]=0;        q.pop();        for(i=0;i<4;i++){            int tx=x+h[i],ty=y+g[i],ts=st[tx][ty]|z;            if(tx<0 || tx>=n || ty<0 || ty>=m)continue;            if(dp[tx][ty][ts]>dp[x][y][z]+map[tx][ty]){                dp[tx][ty][ts]=dp[x][y][z]+map[tx][ty];                pre[tx][ty][ts]=x*1000000+y*10000+z;                if(!vis[tx][ty][ts] && ts==z){                    vis[tx][ty][ts]=1;                    q.push(tx*1000000+ty*10000+ts);                }            }        }    }}void Steiner_Tree(){    int i,j,p,x;    for(p=0;p<K;p++){        for(i=0;i<n;i++)            for(j=0;j<m;j++){if(st[i][j]&&!(st[i][j]&p)) continue;   //没有这一句WA了一晚上                for(x=(p-1)&p;x;x=(x-1)&p){                    if(dp[i][j][p]>dp[i][j][x|st[i][j]]+dp[i][j][(p-x)|st[i][j]]-map[i][j]){                        dp[i][j][p]=dp[i][j][x|st[i][j]]+dp[i][j][(p-x)|st[i][j]]-map[i][j];                        pre[i][j][p]=i*1000000+j*10000+(x|st[i][j]);                    }                }                if(dp[i][j][p]!=INF){                    q.push(i*1000000+j*10000+p);                    vis[i][j][p]=1;                }            }        SPFA();    }}void dfs(int x,int y,int z){    int i,j,k;    ok[x][y]=1;    int t=pre[x][y][z],tx,ty,ts;    if(t==0)return;    tx=t/1000000;    ty=(t-tx*1000000)/10000;    ts=t%10000;    dfs(tx,ty,ts);    if(x==tx&&y==ty) dfs(x,y,(z-ts)|st[x][y]);}void print(){    int i,j,p,q;    for(i=0;i<n;i++)        for(j=0;j<m;j++){            if(st[i][j]==0)continue;            printf("%d\n",dp[i][j][K-1]);            memset(ok,0,sizeof(ok));            dfs(i,j,K-1);            for(p=0;p<n;p++){                for(q=0;q<m;q++){                    if(st[p][q])printf("%c",'x');                    else if(ok[p][q]) printf("%c",'o');                    else printf("%c",'_');                }                printf("\n");            }            return ;        }}int main(){    int i,j;    scanf("%d %d",&n,&m);    init();    Steiner_Tree();    print();    return 0;}



原创粉丝点击