Mars Exploration question (luogu)
Solution
Easy to think of cost flow
To solve the problem the right point, one is not an obstacle point i split into two points ai, bi
From ai to bi even a flow of positive infinity (represented unlimited pass) at a cost of 0 (expressed through these unproductive) side
If the point is i stones, then again from ai to bi even a flow rate of 1 (represented only once through) at a cost of 1 (this represents earnings through 1) the edge
If the point i can point j and i and j are not obstacles, from the bi aj even to a flow of positive infinity, zero cost side
A1 to flow from even a starting point for detecting the number of vehicles at a cost of 0 edge
From bn to the end of a traffic even as the number of probe vehicles at a cost of 0 edge
Running the largest cost maximum flow
Code
#include <cstdio> #include <cstdlib> #include <queue> #include <cstring> #include <algorithm> using namespace std; const int N=3e3,M=1e5; int pre[N],s,t,car,d[N],n,m,incf[N],a[40][40],inf=1<<30,dis[N]; int head[N],nxt[M],ver[M],edge[M],cost[M],tot=1,maxflow,maxcost; bool in[N]; int id(int x,int y,int inv) { return (x-1)*m+y+inv*n*m; } void add(int u,int v,int w,int c) { ver[++tot]=v,nxt[tot]=head[u],edge[tot]=w,cost[tot]=c,head[u]=tot; ver[++tot]=u,nxt[tot]=head[v],edge[tot]=0,cost[tot]=-c,head[v]=tot; } bool spfa() { memset(dis,0x80,sizeof(dis)); memset(pre,0,sizeof(pre)); int last=dis[s]; queue <int> q; dis[s]=0,q.push(s),incf[s]=1<<30; while(!q.empty()) { int u=q.front(); q.pop(); in[u]=false; for(int i=head[u],v;i;i=nxt[i]) if(edge[i]>0 && dis[v=ver[i]]<dis[u]+cost[i]) { dis[v]=dis[u]+cost[i]; incf[v]=min(edge[i],incf[u]); pre[v]=i; if(!in[v]) in[v]=true,q.push(v); } } return dis[t]!=last; } void update() { maxflow+=incf[t],maxcost+=incf[t]*dis[t]; int x=t; while(x!=s) { int i=pre[x]; edge[i]-=incf[t],edge[i^1]+=incf[t]; x=ver[i^1]; } } void dfs(int x,int y,int pos,int k) { int kx,ky,mov; for(int i=head[pos];i;i=nxt[i]) { int v=ver[i]; if(v==s || v==t || v==pos-n*m || edge[i^1]<=0) continue; edge[i^1]--; if(v>n*m) { dfs(x,y,v,k); return; } if(v==(x-1)*m+y+1) kx=x,ky=y+1,mov=1; else kx=x+1,ky=y,mov=0; printf("%d %d\n",k,mov); dfs(kx,ky,v+n*m,k); return; } } int main() { scanf("%d%d%d",&car,&m,&n); s=0,t=n*m*2+1; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&a[i][j]); if(a[n][m]==1 || a[1][1]==1) return 0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { if(a[i][j]==1) continue; add(id(i,j,0),id(i,j,1),inf,0); if(a[i][j]==2) add(id(i,j,0),id(i,j,1),1,1); if(i<n && a[i+1][j]!=1) add(id(i,j,1),id(i+1,j,0),inf,0); if(j<m && a[i][j+1]!=1) add(id(i,j,1),id(i,j+1,0),inf,0); } add(s,id(1,1,0),car,0),add(id(n,m,1),t,car,0); while(spfa()) update(); for(int i=1;i<=maxflow;i++) dfs(1,1,1,i); return 0; }