HDU-4568-Hunter

   题意大致是说给你一个矩阵,其中某些位置有一些宝藏,让你尽可能的取出宝藏并花费最少的代价。矩阵中为-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;
}


你可能感兴趣的:(dp,TSP)