小T准备在家里摆放几幅画,为此他买来了N幅画和N个画框。为了体现他的品味,小T希望能合理地搭配画与画框,使得其显得既不过于平庸也不太违和。对于第 幅画与第 个画框的配对,小T都给出了这个配对的平凡度Aij 与违和度Bij 。整个搭配方案的总体不和谐度为每对画与画框平凡度之和与每对画与画框违和度的乘积。具体来说,设搭配方案中第i幅画与第Pi个画框配对,则总体不和谐度为

小T希望知道通过搭配能得到的最小的总体不和谐度是多少。
小T准备在家里摆放几幅画,为此他买来了N幅画和N个画框。为了体现他的品味,小T希望能合理地搭配画与画框,使得其显得既不过于平庸也不太违和。对于第 幅画与第 个画框的配对,小T都给出了这个配对的平凡度Aij 与违和度Bij 。整个搭配方案的总体不和谐度为每对画与画框平凡度之和与每对画与画框违和度的乘积。具体来说,设搭配方案中第i幅画与第Pi个画框配对,则总体不和谐度为

小T希望知道通过搭配能得到的最小的总体不和谐度是多少。
输入文件第 行是一个正整数T ,表示数据组数,接下来是T组数据。
对于每组数据,第 行是一个正整数N,表示有N对画和画框。
第2到第N+1行,每行有N个非负整数,第i+1 行第j个数表示Aij 。
第N+2到第2*N+1行,每行有N个非负整数,第i+N+1 行第j个数表示Bij 。
包含T行,每行一个整数,表示最小的总体不和谐度
第1幅画搭配第3个画框,第2幅画搭配第1个画框,第3 幅画搭配第2个画框,则总体不和谐度为30
N<=70,T<=3,Aij<=200,Bij<=200
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define MAXN 80
#define MAX 999999999
using namespace std;
int n,ans;
int A[MAXN][MAXN],B[MAXN][MAXN];
struct Vector{
	int x,y;
	friend Vector operator +(const Vector p,const Vector q){return (Vector){p.x+q.x,p.y+q.x};}
	friend Vector operator -(const Vector p,const Vector q){return (Vector){p.x-q.x,p.y-q.y};}
	friend int operator *(const Vector p,const Vector q){return p.x*q.y-p.y*q.x;}
};
inline int read(){
	int date=0,w=1;char c=0;
	while(c<‘0‘||c>‘9‘){if(c==‘-‘)w=-1;c=getchar();}
	while(c>=‘0‘&&c<=‘9‘){date=date*10+c-‘0‘;c=getchar();}
	return date*w;
}
namespace G{
	int f[MAXN],valx[MAXN],valy[MAXN],val[MAXN],map[MAXN][MAXN];
	bool visx[MAXN],visy[MAXN];
	inline void buildgraph(int x,int y){
		for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)map[i][j]=-(x*A[i][j]+y*B[i][j]);
	}
	bool find(int x){
		visx[x]=true;
		for(int i=1;i<=n;i++){
			if(visy[i])continue;
			int t=valx[x]+valy[i]-map[x][i];
			if(!t){
				visy[i]=true;
				if(f[i]==-1||find(f[i])){
					f[i]=x;
					return true;
				}
			}
			else val[i]=min(val[i],t);
		}
		return false;
	}
	Vector KM(){
		Vector s=(Vector){0,0};
		memset(f,-1,sizeof(f));
		memset(valx,0,sizeof(valx));
		memset(valy,0,sizeof(valy));
		for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)valx[i]=max(valx[i],map[i][j]);
		for(int i=1;i<=n;i++){
			memset(val,63,sizeof(val));
			while(1){
				memset(visx,false,sizeof(visx));
				memset(visy,false,sizeof(visy));
				if(find(i))break;
				int w=MAX;
				for(int i=1;i<=n;i++)if(!visy[i])w=min(w,val[i]);
				for(int i=1;i<=n;i++)if(visx[i])valx[i]-=w;
				for(int i=1;i<=n;i++){
					if(visy[i])valy[i]+=w;
					else val[i]-=w;
				}
			}
		}
		for(int i=1;i<=n;i++){
			s.x+=A[f[i]][i];
			s.y+=B[f[i]][i];
		}
		return s;
	}
}
void solve(Vector one,Vector two){
	G::buildgraph(one.y-two.y,two.x-one.x);
	Vector three=G::KM();
	ans=min(ans,three.x*three.y);
	if(((two-one)*(three-one))>=0)return;
	solve(one,three);solve(three,two);
}
void work(){
	Vector one,two;
	G::buildgraph(1,0);
	one=G::KM();
	G::buildgraph(0,1);
	two=G::KM();
	ans=min(one.x*one.y,two.x*two.y);
	solve(one,two);
	printf("%d\n",ans);
}
void init(){
	n=read();
	for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)A[i][j]=read();
	for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)B[i][j]=read();
}
int main(){
	int t=read();
	while(t--){
		init();
		work();
	}
    return 0;
}
原文:https://www.cnblogs.com/Yangrui-Blog/p/9693025.html