BZOJ_2595_[Wc2008]遊覽計劃_斯坦納樹
阿新 • • 發佈:2018-03-11
分享圖片 scan blog pri ont str fin class %d
BZOJ_2595_[Wc2008]遊覽計劃_斯坦納樹
題意:
分析:
斯坦納樹裸題,有幾個需要註意的地方
給出矩陣,不用自己建圖,但枚舉子集轉移時會算兩遍,需要減去當前點的權值
方案記錄比較麻煩,兩邊的轉移都需要記錄,最後dfs找方案會比較容易理解
代碼:
#include <stdio.h> #include <string.h> #include <algorithm> #include <queue> using namespace std; #define N 110 #define LL long long priority_queue <pair <int,int> >q; LL map[11][11],dis[1<<10][N]; int chosex[1<<10][N],chosey[1<<10][N]; bool change[1<<10][N]; int flg[11][11]; int n,m; int tx[]={1,-1,0,0}; int ty[]={0,0,1,-1}; int id[N][N],a[N],xx[N],yy[N],cnt,vis[1<<10][N]; void dfs(int sta,int p){ if(!dis[sta][p])return ; flg[xx[p]][yy[p]]=1; if(change[sta][p]){ dfs(chosex[sta][p],p); dfs(chosey[sta][p],p); }else dfs(sta,id[chosex[sta][p]][chosey[sta][p]]); } int main(){ scanf("%d%d",&n,&m); int i,j,tot=0,k,x; for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ scanf("%lld",&map[i][j]); id[i][j]=++tot; xx[tot]=i;yy[tot]=j; if(!map[i][j]){ a[++cnt]=tot; } } } int mask=(1<<cnt)-1; memset(dis,0x3f,sizeof(dis)); for(i=1;i<=cnt;i++){ dis[1<<i-1][a[i]]=0; } for(j=1;j<=mask;j++){ for(i=1;i<=n*m;i++){ for(k=j&(j-1);k;k=j&(k-1)){ if(dis[j][i]>dis[k][i]+dis[j-k][i]-map[xx[i]][yy[i]]){ dis[j][i]=dis[k][i]+dis[j-k][i]-map[xx[i]][yy[i]]; chosex[j][i]=k,chosey[j][i]=j-k; change[j][i]=1; } // dis[j][i]=min(dis[j][i],dis[k][i]+dis[j-k][i]-map[xx[i]][yy[i]]); } } for(i=1;i<=n*m;i++){ q.push(make_pair(-dis[j][i],i)); } while(!q.empty()){ x=q.top().second;q.pop(); if(vis[j][x])continue; vis[j][x]=1; int nx=xx[x],ny=yy[x]; for(i=0;i<4;i++){ int dx=nx+tx[i],dy=ny+ty[i]; if(dx>=1&&dx<=n&&dy>=1&&dy<=m){ if(dis[j][id[dx][dy]]>dis[j][x]+map[dx][dy]){ dis[j][id[dx][dy]]=dis[j][x]+map[dx][dy]; chosex[j][id[dx][dy]]=nx; chosey[j][id[dx][dy]]=ny; change[j][id[dx][dy]]=0; q.push(make_pair(-dis[j][id[dx][dy]],id[dx][dy])); } } } } } LL ans=1ll<<60; int end; for(i=1;i<=n*m;i++){ if(ans>dis[mask][i]){ ans=dis[mask][i]; end=i; } // ans=min(ans,dis[mask][i]); } dfs(mask,end); printf("%lld\n",ans); for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ if(!map[i][j]){ printf("x"); }else if(flg[i][j]){ printf("o"); }else printf("_"); } puts(""); } }
BZOJ_2595_[Wc2008]遊覽計劃_斯坦納樹