HDU-4568-Hunter

来源:互联网 发布:java之父现在在做什么 编辑:程序博客网 时间:2024/05/21 10:07

   题意大致是说给你一个矩阵,其中某些位置有一些宝藏,让你尽可能的取出宝藏并花费最少的代价。矩阵中为-1的是不能走的,另外走的代价为你经过格子的值,你可以选择任意地点进入与出来。

思路:我先用的Spfa把所有宝藏之间的最短距离算出来,并算出从当前宝藏离开的最短路径。然后就是类似于TSP的DP了,需要注意的是处理-1的情况,也比较简单。后面的转移方程式为dp[j][i]=min(dp[j][k]+dis[k][i]) 其中dp[j][i]表示当前位置在j,得到的宝藏状态为i还需要多少代价完成拿所有的能拿的宝藏。

代码:

#include<cstdio>#include<cstring>#include<iostream>#include<queue>using namespace std;const int inf=1<<29;const int maxn=210;int movex[4]={1,-1,0,0},movey[4]={0,0,1,-1};int n,m,k,a[maxn][maxn],fx[16],fy[16],fo[maxn][maxn],dist[maxn*maxn],dis[16][16];int dp[16][1<<13];bool vis[maxn*maxn];queue<int> q;void Init(){    memset(fo,0,sizeof(fo));}bool isborder(int x,int y){    if(x<0||y<0||x>=n||y>=m)        return true;    return false;}void Spfa(int sx,int sy){    for(int i=0;i<=m*n;i++)        dist[i]=inf;    if(a[sx][sy]==-1)        return;    dist[sx*m+sy]=0;    q.push(sx*m+sy);    while(!q.empty())    {        int u=q.front();        vis[u]=0;        q.pop();        for(int i=0;i<4;i++)        {            int itx=u/m+movex[i];            int ity=u%m+movey[i];            if(isborder(itx,ity))            {                dist[n*m]=min(dist[n*m],dist[u]);            }            else if(a[itx][ity]!=-1)            {                if(dist[itx*m+ity]>dist[u]+a[itx][ity])                {                    dist[itx*m+ity]=dist[u]+a[itx][ity];                    if(!vis[itx*m+ity])                    {                        q.push(itx*m+ity);                        vis[itx*m+ity]=1;                    }                }            }        }    }}void solve(){    for(int i=1;i<=k;i++)     {        Spfa(fx[i],fy[i]);        for(int j=1;j<=k;j++)            dis[i][j]=dist[fx[j]*m+fy[j]];        dis[i][k+1]=dist[n*m];    }    int res=k,fin=(1<<k)-1;    bool is=false;    if(k>1)    {        for(int i=1;i<=k;i++)        {            for(int j=1;j<=k;j++)                if(i!=j&&dis[i][j]!=inf)                {                    is=true;                    break;                }               if(!is)            {                res--;                fin^=(1<<(i-1));            }        }    }    for(int i=1;i<=k;i++)        for(int j=0;j<=fin;j++)            dp[i][j]=inf;    for(int i=1;i<=k;i++)        dp[i][1<<(i-1)]=dis[i][k+1]+a[fx[i]][fy[i]];    for(int i=0;i<=fin;i++)        for(int j=1;j<=k;j++)            for(int l=1;l<=k;l++)                if(l!=j&&(!(i&(1<<(l-1)))))                    dp[l][i|(1<<(l-1))]=min(dp[l][i|(1<<(l-1))],dp[j][i]+dis[j][l]);    int ans=inf;    for(int i=1;i<=k;i++)        ans=min(ans,dp[i][fin]+dis[i][k+1]);    if(ans==inf)        printf("0\n");    else        printf("%d\n",ans);}int main(){    int T;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&n,&m);        for(int i=0;i<n;i++)            for(int j=0;j<m;j++)                scanf("%d",&a[i][j]);        scanf("%d",&k);        for(int i=1;i<=k;i++)        {            scanf("%d%d",&fx[i],&fy[i]);            fo[fx[i]][fy[i]]=i;        }        solve();    }    return 0;}


0 0
原创粉丝点击