题意:在一个n*n的棋盘上有n个棋子,要求通过移动棋子使棋子的排布满足以下情况之一:呈横行排列;呈纵行排列;呈对角线排列(有两条)。
棋子移动一个单元格的费用为1,总费用为所有棋子的移动费用之和。求最小费用。
分析:因为这题的数据很小,故可以枚举每种情况.对于每种情况,我们可以用二分匹配的方法算出最小费用(对于每个棋子,连接n条边到n个目标位置,权值设为负,这样最佳二分匹配求的最大值就是答案的最小值了);
// File Name: 1045.cpp // Author: Zlbing // Created Time: 2013/4/20 15:58:22 #include<iostream> #include<string> #include<algorithm> #include<cstdlib> #include<cstdio> #include<set> #include<map> #include<vector> #include<cstring> #include<stack> #include<cmath> #include<queue> using namespace std; #define CL(x,v); memset(x,v,sizeof(x)); #define INF 1000000000 #define LL long long #define REP(i,r,n) for(int i=r;i<=n;i++) #define RREP(i,n,r) for(int i=n;i>=r;i--) const int MAXN=20; int X[MAXN],Y[MAXN]; int Left[MAXN]; int w[MAXN][MAXN]; int Lx[MAXN],Ly[MAXN]; bool S[MAXN],T[MAXN]; int N; bool match(int i) {S[i]=true;for(int j=1;j<=N;j++)if(Lx[i]+Ly[j]==w[i][j]&&!T[j]){T[j]=true;if(Left[j]==0||match(Left[j])){Left[j]=i;return true;}}return false; } void update(){int a=INF;for(int i=1;i<=N;i++)if(S[i])for(int j=1;j<=N;j++)if(!T[j])a=min(a,Lx[i]+Ly[j]-w[i][j]);for(int i=1;i<=N;i++){if(S[i])Lx[i]-=a;if(T[i])Ly[i]+=a;} } void KM() {for(int i=1;i<=N;i++){Left[i]=Lx[i]=Ly[i]=0;for(int j=1;j<=N;j++){Lx[i]=max(Lx[i],w[i][j]);}}for(int i=1;i<=N;i++){for(;;){CL(S,0);CL(T,0);if(match(i))break;else update();}} }int main() {int cas=0; while(~scanf("%d",&N)){if(N==0)break;REP(i,1,N){int a,b;scanf("%d%d",&a,&b);X[i]=a;Y[i]=b;}int ans=INF;REP(i,1,N){REP(k,1,N)REP(j,1,N){int dist=abs(X[k]-i)+abs(Y[k]-j);w[k][j]=-dist;}KM();int minn=0;REP(i,1,N){minn+=-w[Left[i]][i];}ans=min(ans,minn);}REP(i,1,N) {REP(k,1,N)REP(j,1,N){int dist=abs(X[k]-j)+abs(Y[k]-i);w[k][j]=-dist;}KM();int minn=0;REP(i,1,N)minn+=-w[Left[i]][i];ans=min(ans,minn);}REP(k,1,N)REP(i,1,N){int dist=abs(X[k]-i)+abs(Y[k]-i);w[k][i]=-dist;}KM();int minn=0;REP(i,1,N)minn+=-w[Left[i]][i];ans=min(ans,minn);REP(k,1,N)REP(i,1,N){int dist=abs(X[k]-i)+abs(Y[k]-N+i-1);w[k][i]=-dist;}KM();minn=0;REP(i,1,N)minn+=-w[Left[i]][i];ans=min(ans,minn);printf("Board %d: %d moves required.\n\n",++cas,ans);}return 0; }