昨天比赛,2010年多校第9场,貌似我们九个人中就我一个人研究了这题,也研究了一个多小时,而且刚开始对题意的理解用手算是过了样例,然后程序写出来时发现不对,手算的时候算错了,然后又读了题,然后觉得另一种题意应该是对的,在提交WA了几次之后我是终于彻彻底底明白题意了,但是比赛差不多结束了,而且受当时题意读错的影响,真明白的题意的时候思路扩展不开,就想到暴力的搜索了,然后就是预想中的TLE了!!!
貌似好多人都读不懂题:题中刚开始说有图,然后图的密度什么的,然后就是防止盗版,然后两个图的相似度是按照所有格子的距离和来算的,对于两个图中第i个格子的距离,即为第i个格子的数在整个图中n个格子的排名的绝对值差
然后题中图的每个格子的值为1~n,即代表的是格子在图中的排名的。
然后题中给了n和m,n代表一个图分的格数,有m个图,让你找一个图,使得这m个图到这个图的距离最小,并且这个图也必须满足给的图的性质,即每个格子的数的值是不同的(1~n).
解题思路:对于我们要找的目标图,它的每个格子可以取1~n的任意一个数,我们可以暴力求得第i个格子取1~n的任意一个值时m个图在这个格子的值,因为一个格子可以匹配1~n中的任意一个数,并且n个格子匹配的数都不同,于是很自然的想到了二分图最小带权匹配。。。
下面是代码:
/
// File Name: yes.cpp
// Author: wang
// mail:
// Created Time: 2013-8-14 8:28:57
/
#include <cstdio>
#include <cstdlib>
#include <climits>
#include <cstring>
#include <cmath>
#include <algorithm>
#include<iostream>
#include<queue>
#include <map>
using namespace std;
typedef long long ll;
#define INF (INT_MAX/10)
#define SQR(x) ((x)*(x))
#define rep(i, n) for (int i=0; i<(n); ++i)
#define repf(i, a, b) for (int i=(a); i<=(b); ++i)
#define repd(i, a, b) for (int i=(a); i>=(b); --i)
#define clr(ar,val) memset(ar, val, sizeof(ar))
#define inf 1000000000
#define N 205
class match{
public:
int lx[N],ly[N];
int Stack[N],next[N];
bool visx[N],visy[N];
int n;
vector<int>vec[N];
void init()
{
rep(i,n+1) vec[i].clear();
memset(next,-1,sizeof(next));
}
bool bfs(int u)
{
visx[u]=true;
rep(i,vec[u].size())
{
if(visy[i]==true) continue;
if(lx[u]+ly[i]==vec[u][i])
{
visy[i]=true;
if(next[i]==-1 || bfs(next[i]))
{
next[i]=u; return true;
}
}
else
Stack[i]=min(Stack[i],lx[u]+ly[i]-vec[u][i]);
}
return false;
}
int km()
{
rep(i,n) lx[i]=-inf;
rep(i,n)
{
ly[i]=0;
rep(j,n)
lx[i]=max(lx[i],vec[i][j]);
}
rep(i,n)
{
while(true)
{
memset(visx,false,sizeof(visx));
memset(visy,false,sizeof(visy));
rep(j,n) Stack[j]=inf;
if(bfs(i)) break;
int Min=inf;
rep(j,n)
if(visy[j]==false)
Min=min(Min,Stack[j]);
rep(j,n)
{
if(visx[j]==true) lx[j]-=Min;
if(visy[j]==true) ly[j]+=Min;
}
}
}
int ans=0;
rep(i,n)
ans+=vec[next[i]][i];
return ans;
}
};
match sa;
int n,m;
int a[N][N];
void solve()
{
scanf("%d%d",&n,&m);
rep(i,m)
rep(j,n)
scanf("%d",&a[i][j]),--a[i][j];//转换为0~n-1的
sa.n=n;
sa.init();
rep(i,n)
{
rep(j,n)//n个数的
{
int sum=0;
rep(k,m)
sum+=-abs(j-a[k][i]);
sa.vec[i].push_back(sum);//i与j匹配的
}
}
printf("%d\n",-sa.km());
}
int main()
{
int test;
scanf("%d",&test);
repf(ror,1,test)
{
printf("Case #%d: ",ror);
solve();
}
return 0;
}