題解 [USACO 2013 Jan]Island Travels
阿新 • • 發佈:2020-08-10
狀壓dp,
大概是這題 + 這題
\(~bfs~\)求出聯通塊(島嶼),每個聯通塊就是一個獨立的節點,
所以兩點的距離也可以用\(~bfs~\)求?
這樣其實是錯的,\(~bfs~\)出來的不是最短距離,還要用上\(~Floyd~\)。
最後套\(~Hamiton~\)板子即可。
\(Code\):
#include<bits/stdc++.h> using namespace std; const int N=51; const int M=5000; int dx[4]={0,1,0,-1}; int dy[4]={1,0,-1,0}; int n,m,cnt,fr[N][N],d[N][N],ans=INT_MAX,f[1<<17][17]; char mp[N][N]; bool vis[N][N]; void Floyd(){ for(int k=1;k<=cnt;k++) for(int i=1;i<=cnt;i++) for(int j=1;j<=cnt;j++) d[i][j]=min(d[i][j],d[i][k]+d[k][j]); } void bfs(int x,int y){ queue<int>q1,q2; q1.push(x);q2.push(y); vis[x][y]=true; fr[x][y]=cnt; while(!q1.empty()){ int nx=q1.front();q1.pop(); int ny=q2.front();q2.pop(); for(int i=0;i<4;i++){ int fx=nx+dx[i]; int fy=ny+dy[i]; if(fx<1||fy<1||fx>n||fy>m||vis[fx][fy]||mp[fx][fy]!='X') continue; fr[fx][fy]=cnt;vis[fx][fy]=true; q1.push(fx);q2.push(fy); } } } void BFS(int x,int y){ queue<int>q1,q2,q3; q1.push(x); q2.push(y); q3.push(0); vis[x][y]=true; while(!q1.empty()){ int nx=q1.front();q1.pop(); int ny=q2.front();q2.pop(); int len=q3.front();q3.pop(); for(int i=0;i<4;i++){ int fx=nx+dx[i]; int fy=ny+dy[i]; if(fx<1||fy<1||fx>n||fy>m||vis[fx][fy]||mp[fx][fy]=='.') continue; d[fr[x][y]][fr[fx][fy]]=min(d[fr[x][y]][fr[fx][fy]],len); // cout<<fr[x][y]<<' '<<fr[fx][fy]<<' '<<len+1<<endl; vis[fx][fy]=true; q1.push(fx);q2.push(fy);q3.push(len+1); } } } void DP(){ memset(f,0x3f,sizeof(f)); for(int i=1;i<=cnt;i++) f[1<<(i-1)][i]=0; for(int i=1;i<(1<<cnt);i++) for(int j=1;j<=cnt;j++)if(i>>(j-1)&1) for(int k=1;k<=cnt;k++)if((i^(1<<(j-1)))>>(k-1)&1) f[i][j]=min(f[i][j],f[i^(1<<(j-1))][k]+d[k][j]); for(int i=1;i<=cnt;i++) ans=min(ans,f[(1<<cnt)-1][i]); printf("%d",ans); } int main(){ memset(d,0x3f,sizeof(d)); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>mp[i][j]; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ if(vis[i][j]||mp[i][j]!='X')continue; cnt++;bfs(i,j); } memset(vis,0,sizeof(vis)); // for(int i=1;i<=n;i++){ // for(int j=1;j<=m;j++) // if(mp[i][j]!='X')cout<<mp[i][j]<<' '; // else cout<<fr[i][j]<<' '; // cout<<endl; // } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ if(mp[i][j]!='X')continue; memset(vis,0,sizeof(vis)); d[i][i]=0;BFS(i,j); } // for(int i=1;i<=cnt;i++){ // for(int j=1;j<=cnt;j++) // printf("%d---->%d: %d\n",i,j,d[i][j]); // } Floyd(); DP(); return 0; } /* 4 5 ...XX .XXX. X...X .XXXX */ /* 2 5 . . . 1 1 . 2 2 X . */