NC51316. Going Home
描述
输入描述
There are one or more test cases in the input. Each case starts with a line giving two integers N and M, where N is the number of rows of the map, and M is the number of columns. The rest of the input will be N lines describing the map. You may assume both N and M are between 2 and 100, inclusive. There will be the same number of 'H's and 'm's on the map; and there will be at most 100 houses. Input will terminate with 0 0 for N and M.
输出描述
For each test case, output one line with the single integer, which is the minimum amount, in dollars, you need to pay.
示例1
输入:
2 2 .m H. 5 5 HH..m ..... ..... ..... mm..H 7 8 ...H.... ...H.... ...H.... mmmHmmmm ...H.... ...H.... ...H.... 0 0
输出:
2 10 28
C++(clang++ 11.0.1) 解法, 执行用时: 3ms, 内存消耗: 420K, 提交时间: 2023-08-08 21:57:33
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; #define x first #define y second typedef pair<int,int>PII; const int N=110; const int INF=0x3f3f3f3f; int n,m,P,H; char s[N][N]; PII p[N],h[N]; int a[N][N]; int lx[N],ly[N]; int match[N]; bool vx[N],vy[N]; bool dfs(int u){ vx[u]=1; for(int i=1;i<=H;i++){ if(vy[i] || lx[u]+ly[i]!=a[u][i]) continue; vy[i]=1; if(match[i]==-1 || dfs(match[i])){ match[i]=u; return true; } } return false; } int main(){ while(scanf("%d%d",&n,&m),n&&m){ P=H=0; for(int i=1;i<=n;i++) scanf("%s",s[i]+1); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ if(s[i][j]=='m') p[++P]=make_pair(i,j); if(s[i][j]=='H') h[++H]=make_pair(i,j); } for(int i=1;i<=P;i++) for(int j=1;j<=H;j++) a[i][j]=-(abs(p[i].x-h[j].x)+abs(p[i].y-h[j].y)); memset(lx,-0x3f,sizeof(lx)); memset(ly,0,sizeof(ly)); memset(match,-1,sizeof(match)); for(int i=1;i<=P;i++){ while(true){ memset(vx,0,sizeof(vx)); memset(vy,0,sizeof(vy)); if(dfs(i)) break; int dt=INF; for(int j=1;j<=P;j++){ if(!vx[j]) continue; for(int k=1;k<=H;k++){ if(vy[k]) continue; dt=min(dt,lx[j]+ly[k]-a[j][k]); } } for(int j=1;j<=P;j++) if(vx[j]) lx[j]-=dt; for(int j=1;j<=H;j++) if(vy[j]) ly[j]+=dt; } } int ans=0; for(int i=1;i<=P;i++) ans=ans+lx[i]+ly[i]; printf("%d\n",-ans); } return 0; }
C++(g++ 7.5.0) 解法, 执行用时: 3ms, 内存消耗: 428K, 提交时间: 2022-10-16 15:24:28
#include<iostream> #include<cstring> #define _for(i,L,R) for(int i=L;i<=R;++i) //#define int long long using namespace std; using node=pair<int,int>; #define x first #define y second const int N=1e2+5,INF=0x3f3f3f3f; node h[N],p[N]; int visx[N], visy[N], lx[N], ly[N], link[N], g[N][N]; int n, m; bool dfs(int x,int m) { visx[x]=1; _for(i,1,m){ if(!visy[i] and lx[x]+ly[i]==g[x][i]){ visy[i]=1; if(link[i]==-1 or dfs(link[i],m)) return link[i]=x,1; } } return 0; } int KM(int n,int m) { memset(ly,0,sizeof ly); memset(lx,-0x3f,sizeof lx); memset(link,-1,sizeof link); _for(i,1,n) _for(j,1,m) lx[i]=max(lx[i],g[i][j]); _for(i,1,n) while(true){ memset(visx,0,sizeof visx); memset(visy,0,sizeof visy); if(dfs(i,m)) break; int d=INF; _for(j,1,n) if(visx[j]) _for(k,1,m) if(!visy[k]) d=min(d,lx[j]+ly[k]-g[j][k]); if(d==INF) return -1; _for(j,1,n) if(visx[j]) lx[j]-=d; _for(j,1,n) if(visy[j]) ly[j]+=d; } return 1; } void solve() { while(~scanf("%d%d",&n,&m) and (n or m)){ int nh=0,np=0; _for(i,1,n) _for(j,1,m){ char c; cin>>c; if(c=='H') h[++nh]={i,j}; if(c=='m') p[++np]={i,j}; } _for(i,1,np) _for(j,1,nh) g[i][j]=-abs(h[j].x-p[i].x)-abs(h[j].y-p[i].y); KM(np,nh); int res=0; _for(i,1,nh) res+=-g[link[i]][i]; printf("%d\n",res); } } signed main() { int T = 1; // scanf("%d",&T); while(T--) solve(); return 0; }