HDU-4568 TSP + shortest circuit

Keywords: PHP less

Meaning: for a matrix with n rows and m columns, the number on the matrix represents the passing cost (pay attention here to pay for each passing cost). There are several treasures on the matrix. The hunter can go in from any boundary, get all the treasures from the matrix and come out from any boundary.

Solution: it should be easy to think of TSP problem as soon as the number of treasures is less than or equal to 13 and must pass through. So we use the shortest path pretreatment + state compression DP to solve it. First of all, preprocess the shortest path from all treasure points to the whole map, which is to prepare for the subsequent DP cost, and then start pressing DP. Design DP state as dp[S][now] to represent the minimum value of the treasure point set as s and now in the now treasure point. Just use the memory search to transfer.

See the code for details. You should understand it very well:

#include<bits/stdc++.h>
using namespace std;
const int N=210;
const int INF=0x3f3f3f3f;
const int dx[]={-1,0,1,0};
const int dy[]={0,1,0,-1};
int n,m,k,a[N][N],dp[1<<15][15],es[N],px[N],py[N];

struct dat{
    int d,x,y;
    bool operator < (const dat &rhs) const {
        return d>rhs.d;
    }
};
priority_queue<dat> q;
int dis[15][N][N];
bool vis[N][N];
void Dijkstra(int k) {
    memset(dis[k],0x3f,sizeof(dis[k]));
    memset(vis,0,sizeof(vis));
    q.push((dat){0,px[k],py[k]});
    dis[k][px[k]][py[k]]=0;
    while (!q.empty()) {
        dat u=q.top(); q.pop();
        if (vis[u.x][u.y]) continue;
        vis[u.x][u.y]=1;
        for (int i=0;i<4;i++) {
            int tx=u.x+dx[i],ty=u.y+dy[i];
            if (tx<1 || tx>n || ty<1 || ty>m || a[tx][ty]==-1) continue;
            if (dis[k][tx][ty]>dis[k][u.x][u.y]+a[tx][ty]) {
                dis[k][tx][ty]=dis[k][u.x][u.y]+a[tx][ty];
                q.push((dat){dis[k][tx][ty],tx,ty});
            }
        }
    }
}

int lowbit(int x) { int ret=0; for (;x;x-=x&-x) ret++; return ret; }

int dfs(int now,int x) {
    if (dp[now][x]!=-1) return dp[now][x];
    if (lowbit(now)==1) return es[x]+a[px[x]][py[x]];
    dp[now][x]=INF;
    for (int i=1;i<=k;i++)
        if ((i!=x) && (now&(1<<i-1))) {
            int tmp=dfs(now^(1<<x-1),i)+dis[i][px[x]][py[x]];
            dp[now][x]=min(dp[now][x],tmp);
    }
    return dp[now][x];    
}

int main()
{
    int T; cin>>T;
    while (T--) {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) scanf("%d",&a[i][j]);
        scanf("%d",&k);
        for (int i=1;i<=k;i++) {
            scanf("%d%d",&px[i],&py[i]); 
            px[i]++; py[i]++;
            Dijkstra(i);
            es[i]=INF;
            for (int j=1;j<=n;j++) es[i]=min(es[i],min(dis[i][j][1],dis[i][j][m]));
            for (int j=1;j<=m;j++) es[i]=min(es[i],min(dis[i][1][j],dis[i][n][j]));
        }
        memset(dp,-1,sizeof(dp));
        int ans=INF;
        for (int i=1;i<=k;i++) ans=min(ans,dfs((1<<k)-1,i)+es[i]);
        if (ans==INF) printf("-1"); else printf("%d\n",ans);
    }
    return 0;
}

Posted by bruckerrlb on Sat, 02 Nov 2019 10:43:10 -0700