hdu 4568 Hunter

来源:互联网 发布:java流程图生成工具 编辑:程序博客网 时间:2024/05/21 09:18

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4568

题意:给定一个矩阵图,每走一个格子有一个花费,可以从任意边进入,任意边出去,并且图中有k个点要求全部走到,问最少的花费是多少,如果不能够全部走到,输出0。

思路:先用spfa对图做预处理,求出所有必须走的点和地图外构成的图的任意两点的最短路,然后就是枚举必须走的点的访问顺序问题,由于k很小,可以用状态压缩DP,dp[i][j]表示最后选的点是i,j表示已经选的点。


#include<cstdio>#include<cstring>#include<algorithm>#include<queue>using namespace std;const int inf=2099999999;int s[205][205],ma[205][205];int dis[15][15],c[15];int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};int n,m;int f[15];int dp[15][1<<14];int d[40005],vis[40005];struct node{    int di,u;    bool operator <(const node& rhs) const{        return di>rhs.di;    }};void spfa(int st,int num){    int i;    priority_queue<node> q;    for(i=0;i<n*m;i++) d[i]=inf;    d[st]=0;    memset(vis,0,sizeof(vis));    q.push((node){0,st});    while(!q.empty()){        node p=q.top();        q.pop();        int u=p.u;        if(vis[u]) continue;        vis[u]=1;        int x,y,xx,yy,xu;        x=u/m,y=u%m;        if(ma[x][y]>-1) dis[num][ma[x][y]]=d[u];        if(x==0||x==n-1||y==0||y==m-1) c[num]=min(c[num],d[u]);        for(i=0;i<4;i++){            xx=x+dir[i][0];            yy=y+dir[i][1];            if(s[xx][yy]==-1) continue;            if(xx>n-1||xx<0||yy>m-1||yy<0) continue;            xu=xx*m+yy;            if(d[xu]>d[u]+s[xx][yy]){                d[xu]=d[u]+s[xx][yy];                q.push((node){d[xu],xu});            }        }    }}int main(){    int i,j,k,K,x,y,state;    int t;    scanf("%d",&t);    while(t--){        scanf("%d%d",&n,&m);        for(i=0;i<n;i++)         for(j=0;j<m;j++)           scanf("%d",&s[i][j]);        memset(ma,-1,sizeof(ma));        memset(dp,0x7f,sizeof(dp));        memset(dis,0,sizeof(dis));        scanf("%d",&K);        for(i=0;i<K;i++){            int a,b;            scanf("%d%d",&a,&b);            ma[a][b]=i;            f[i]=a*m+b;            c[i]=inf;        }        for(i=0;i<K;i++) spfa(f[i],i);        for(i=0;i<K;i++){            x=f[i]/m,y=f[i]%m;            dp[i][1<<i]=c[i]+s[x][y];        }        for(i=1;i<(1<<K);i++){        for(j=0;j<K;j++){            for(k=0;k<K;k++){                if((i&(1<<j))&&(i&(1<<k))&&j!=k){                    if(dp[j][i^(1<<k)]!=inf) dp[k][i] = min(dp[k][i], dp[j][i^(1<<k)]+dis[j][k]);                }            }        }    }        int ans=inf;        for(i=0;i<K;i++)          ans=min(ans,dp[i][(1<<K)-1]+c[i]);        printf("%d\n",ans);    }    return 0;}


原创粉丝点击