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); } };