http://acm.hdu.edu.cn/showproblem.php?pid=4856
西安邀请赛的一道题,这道题我们当时在现场最后1h才发现时状态压缩dp,惊险写出
现在回头想发现当时有点呆,这种明显tsp模型的题目当时鬼迷心窍去写搜索,超时而不知悔改,实际是水题一道
#include <iostream> #include <map> #include <cstdio> #include <cstring> #include <queue> using namespace std ; const int INF=0xfffffff ; int n,m ; char M[25][25] ; int vis[25][25] ; int dis[25][25] ; int dx[]={1,-1,0,0} ; int dy[]={0,0,1,-1} ; int dp[16][1<<16] ;//在管道i时,状态为s struct node { int x1,y1,x2,y2 ; }kk[25] ; struct point { int x,y,step ; } ; int bfs(node a,node b) { memset(vis,0,sizeof(vis)) ; queue <point> q ; point s ; s.x=a.x2 ;s.y=a.y2 ;s.step=0 ; vis[s.x][s.y]=1 ; q.push(s) ; while(!q.empty()) { point u=q.front() ; q.pop() ; if(u.x==b.x1 && u.y==b.y1) { return u.step ; } for(int i=0 ;i<4 ;i++) { int xx=u.x+dx[i] ; int yy=u.y+dy[i] ; if(xx<0 || xx>=n || yy<0 || yy>=n)continue ; if(M[xx][yy]=='#')continue ; if(vis[xx][yy])continue ; vis[xx][yy]=1 ; point next ; next.x=xx ;next.y=yy ;next.step=u.step+1 ; q.push(next) ; } } return INF ; } void INIT() { for(int i=0 ;i<25 ;i++) for(int j=0 ;j<25 ;j++) dis[i][j]=INF ; for(int i=0 ;i<m ;i++) { for(int j=0 ;j<m ;j++) { if(i==j) { dis[i][j]=0 ; continue ; } dis[i][j]=bfs(kk[i],kk[j]) ; } } } int main() { while(~scanf("%d%d",&n,&m)) { for(int i=0 ;i<n ;i++) scanf("%s",M[i]) ; for(int i=0 ;i<m ;i++) { scanf("%d%d%d%d",&kk[i].x1,&kk[i].y1,&kk[i].x2,&kk[i].y2) ; kk[i].x1-- ;kk[i].y1-- ;kk[i].x2-- ;kk[i].y2-- ; } INIT() ; for(int i=0 ;i<16 ;i++) for(int j=0 ;j<(1<<16) ;j++) dp[i][j]=INF ; for(int i=0 ;i<m ;i++)dp[i][1<<i]=0 ; int ans=INF ; for(int i=0 ;i<(1<<m) ;i++) { for(int j=0 ;j<m ;j++) { if(i&(1<<j)) { for(int k=0 ;k<m ;k++) { if(dis[k][j]==INF || !(i&(1<<k)))continue ; dp[j][i]=min(dp[j][i],dp[k][i^(1<<j)]+dis[k][j]) ; } } } } for(int i=0 ;i<m ;i++) ans=min(ans,dp[i][(1<<m)-1]) ; if(ans==INF)puts("-1") ; else printf("%d\n",ans) ; } return 0 ; }