zoukankan      html  css  js  c++  java
  • HDU-4568 TSP+最短路

    题意:给一个n行m列的矩阵,矩阵上的数字代表经过代价(这里要注意每经过一次都要付出代价),矩阵上有几个宝藏,猎人可以从任意边界进去矩阵取完所有宝藏后从任意边界出来。

    解法:一看到宝藏数量小于等于13且必须经过,应该很容易想到TSP问题。所以我们用最短路预处理+状态压缩DP解决。首先预处理所有宝藏点到整个地图的最短路这是为了后续的dp代价做准备,然后开始状压dp,设计dp状态为dp[S][now]代表现在去了的宝藏点集为S且现在在now宝藏点的最小值,用记忆化搜索转移即可。

    细节详见代码,应该挺好懂的:

    #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
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    C语言位操作
    Ribbon负载规则的替换
    Nginx 的配置文件
    Nginx 操作常用的命令
    Nginx 是什么?
    SpringCloud Eureka 新版本依赖
    @Autowired 与@Resource的区别
    spring 注释
    redis 的 rdb 和 aof 持久化的区别
    jdk1.7下HashMap的头插法问题
  • 原文地址:https://www.cnblogs.com/clno1/p/10934224.html
Copyright © 2011-2022 走看看