HDU 4856

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 ;

}
View Code

 

你可能感兴趣的:(HDU)