zoukankan      html  css  js  c++  java
  • b_vj_Hunter(dij预处理宝藏与宝藏外界的最短距离+状压dp)

    有一个n*m的网格,正数格子代表被研究的费用,-1代表不能被研究,且网格中有k个宝藏;问一个宝藏猎人以网格外部为起点进入网格,并收集所有宝藏回到起点的最小花费。(1<=K<=13,n,m<=200)

    思路:f[i][j]表示终点在宝藏i,且宝藏状态为j时的最少花费;
    由于要回到起点,所以在dijkstra中用out[id]表示从i走到边界的最短距离

    #include<iostream>
    #include<math.h>
    #include<queue>
    using namespace std;
    const int N=205, M=20, inf=0x3f3f3f3f, dir[4][2] = { {1,0},{0,-1},{0,1},{-1,0} };
    int n,m,K,d[N][N],sp[N][N],g[N][N],out[N],f[M][1<<M];
    struct node {
        int x,y,w;
    }T[N];
    struct cmp{
        bool operator()(node& a, node& b){
            return a.w > b.w;
        }
    };
    void dij(int sx, int sy, int id) {
        for (int i=0; i<n; i++) for (int j=0; j<m; j++) sp[i][j]=inf;
        priority_queue<node, vector<node>, cmp> q;
        q.push({sx,sy,0}), sp[sx][sy]=0;
        while (!q.empty()) {
            int x=q.top().x, y=q.top().y; q.pop();
            if (x==0 || x==n-1 || y==0 || y==m-1)  //宝藏到边界的距离,注g[sx][sy]的花费没有尚未算进去
                out[id]=min(out[id], sp[x][y]);
            for (int k=0; k<4; k++) {
                int tx=x+dir[k][0], ty=y+dir[k][1];
                if (tx>=0 && tx<n && ty>=0 && ty<m && g[tx][ty]!=-1 && sp[tx][ty]>sp[x][y]+g[tx][ty]) {
                    sp[tx][ty]=sp[x][y]+g[tx][ty];
                    q.push({tx,ty,sp[tx][ty]});
                }
            }
        }
    }
    int main() {
        std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        int q; cin>>q;
        while (q--) {
            cin>>n>>m;
            for (int i=0; i<n; i++)
            for (int j=0; j<m; j++)
                cin>>g[i][j];
            cin>>K;
            for (int i=0; i<K; i++) cin>>T[i].x>>T[i].y;
            //求出宝藏与宝藏之间的最短距离(注:dij只能求单源最短路)
            for (int i=0; i<K; i++) {
                out[i]=inf; //out[i]就是宝藏到外界的最短距离
                dij(T[i].x,T[i].y,i);
                for (int j=0; j<K; j++) {
                    d[i][j]=sp[T[j].x][T[j].y];
                }
            }
            int tot=1<<K, ans=inf;
            for (int i=0; i<K; i++) for (int j=0; j<tot; j++) f[i][j]=inf;
            for (int i=0; i<K; i++) f[i][1<<i]=g[T[i].x][T[i].y]+out[i]; //外界到宝藏i的距离
            
            for (int j=0; j<tot; j++)
            for (int s=0; s<K; s++) if (j&(1<<s) && f[s][j]!=inf) {
                for (int e=0; e<K; e++) if ((j&(1<<e))==0) 
                    f[e][j|(1<<e)]=min(f[e][j|(1<<e)], f[s][j]+d[s][e]);
            }
            for (int i=0; i<K; i++) ans=min(ans, f[i][tot-1]+out[i]); //终点在i,且从i出去
            cout<<ans<<'
    ';
        }
        return 0;
    }
    
  • 相关阅读:
    内排序小结
    HTML初体验
    android动画介绍之 自己定义Animation动画实现qq抖一抖效果
    iOS 把数据库文件打包到mainbundle中,查找不到路径的解决的方法;以及在删除bundle中文件的可行性
    随着ScrollView的滑动,渐渐的运行动画View
    MFC Month Calendar Control 控件使用
    Codeforces Round #148 (Div. 1)
    Codeforces 486E LIS of Sequence(线段树+LIS)
    2014年百度之星资格赛第四题Labyrinth
    UVA10519
  • 原文地址:https://www.cnblogs.com/wdt1/p/13940843.html
Copyright © 2011-2022 走看看