zoukankan      html  css  js  c++  java
  • LC 1368. Minimum Cost to Make at Least One Valid Path in a Grid

    link

     Solution 1 : min cost flow

    Break each cell into two nodes i and i', connect i to i' (i+mn) with an edge with flow 1, cost 0. For each cell i, consider 4 adjacent cells j, connect i' to j with an edge with flow 1, if we can get to j without direction change, the cost is 0, else the cost is 1.
    Add Source and Target point, connect Source to 0 with flow 1, cost 0; connect 2mn-1 (mn-1+mn) to T with flow 1, cost 0.
    Using spfa to find the path each time, EK algo to find the max flow.

    class Solution {
    public:
        int m,n;
        int S,T;
        int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
        int head[30000];
        struct Edge{
            int to;
            int next;
            int remain;
            int fi;
        }e[300000];
        int en;
        
        void add(int from, int to, int flow, int fi){
            addEdge(from,to,flow,fi);
            addEdge(to,from,0,-fi);
        }
        
        void addEdge(int from, int to, int flow, int fi){
            e[en].next=head[from];
            e[en].to=to;
            e[en].remain=flow;
            e[en].fi=fi;
            head[from]=en;
            ++en;
        }
        
        int minCost(vector<vector<int>>& grid) {
            en=0;
            memset(head,-1,sizeof(head));
            m=grid.size();
            n=grid[0].size();
            S=2*m*n;
            T=2*m*n+1;
            
            add(S,0,1,0);
            add(2*m*n-1,T,1,0);
            for(int i=0;i<m*n;i++){
                add(i,i+m*n,1,0);
                int x=i/n;
                int y=i%n;
                for(int d=0;d<4;d++){
                    int nx=x+dir[d][0];
                    int ny=y+dir[d][1];
                    if(nx<0 || nx>=m || ny<0 || ny>=n) continue;
                    if(d+1!=grid[x][y]){
                       
                        add(i+m*n,nx*n+ny,1,1);
                    }else{
                        add(i+m*n,nx*n+ny,1,0);
                    }
                }
            }
            return EK();
        }
        
        int EK(){
            int res=0;
            
            while(true){
                vector<int> dis(2*m*n+2,INT_MAX);
                vector<int> pre(2*m*n+2,-1);
                spfa(pre,dis);
                if(pre[T]==-1) break;
                int v=T;
                while(true){
                    int edge=pre[v];
                    e[edge].remain--;
                    e[edge^1].remain++;
                    v=e[edge^1].to;
                    if(v==S) break;
                }
                
                res+=dis[T];
            }
            return res;
        }
        
        void spfa(vector<int> &pre, vector<int> &dis){
            queue<int> q;
            vector<int> iq(2*m*n+2,0);
            
            q.push(S);
            iq[S]=1;
            dis[S]=0;
            while(!q.empty()){
                int cur=q.front();
                q.pop();
                iq[cur]=0;
                
                for(int i=head[cur];i!=-1;i=e[i].next){
                    int v=e[i].to;
                    
                    if(e[i].remain>0 && dis[v]>dis[cur]+e[i].fi){
                        dis[v]=dis[cur]+e[i].fi;
                        pre[v]=i;
                        if(iq[v]==0){
                            iq[v]=1;
                            q.push(v);
                        }
                    }
                }
            }
        }
        
       
    };

    Solution 2: BFS + DFS

    class Solution {
    public:
        int m,n;
        int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
        int cost;
        vector<vector<int>> _grid;
        int minCost(vector<vector<int>>& grid) {
            m=grid.size();
            n=grid[0].size();
            _grid=grid;
            vector<vector<int>> res(m,vector<int>(n,INT_MAX));
            queue<pair<int,int>> q;
            cost=0;
            dfs(0,0,q,res);
            while(!q.empty()){
                cost++;
                int size=q.size();
                for(int i=0;i<size;++i){
                    auto cur=q.front();
                    q.pop();
                    for(int d=0;d<4;d++){
                        dfs(cur.first+dir[d][0],cur.second+dir[d][1],q,res);
                    }
                }
            }
            return res[m-1][n-1];
        }
        
        void dfs(int r, int c, queue<pair<int,int>> &q, vector<vector<int>> &res){
            if(r<0 || r>=m || c<0 || c>=n) return;
            if(res[r][c]!=INT_MAX) return;
            res[r][c]=cost;
            q.push({r,c});
            int d=_grid[r][c]-1;
            dfs(r+dir[d][0],c+dir[d][1],q,res);
        }
    };
  • 相关阅读:
    技术文章应该怎么写?
    后退时保存表单状态
    [原]长表头表格 竖直仅滚动内容区 水平滚动表头和内容区
    IE7不经提示关闭浏览器窗口
    meta 标记
    demo : 简单的 xslt 递归解析 xml 成 tree
    使用iframe和table模拟frameset的resize功能.html
    一个下划线(_)引发的"疑难杂症"
    几点小东西
    使用 ActiveReports 的 subReport 几点疑惑
  • 原文地址:https://www.cnblogs.com/FEIIEF/p/12389883.html
Copyright © 2011-2022 走看看