题目链接:点击查看
题目大意:给出一个 n * m 的矩阵,每个格子中都有一个数字,代表需要运货的次数,现在需要选出一个点作为仓库,使得累计运货的路程最短
题目分析:真没想到数据水到能让 n^4 的算法水过去,多的就不说了,一会会挂暴力的头铁代码的
重点想说一下如何用中位数解决这个问题,关于中位数处理类似的一维问题,我们只需要求出 x 轴上的中位数,选取该位置作为仓库肯定是最优的了,那么在二维平面该如何选择呢,其实也是同理,我们只需要沿着行开始遍历,确定下来 x 的坐标,然后再沿着列开始遍历,确定下来 y 的坐标,这样就可以确定下来仓库的具体位置,剩下的 n^2 计算出答案就好了
代码:
中位数:
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const int N=110;
LL a[N][N];
int main()
{
#ifndef ONLINE_JUDGE
// freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
#endif
// ios::sync_with_stdio(false);
int w;
cin>>w;
while(w--)
{
int n,m;
scanf("%d%d",&m,&n);
LL sum=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
scanf("%lld",&a[i][j]);
sum+=a[i][j];
}
int x,y;
LL mid=sum+1>>1;
LL now=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
now+=a[i][j];
if(now>=mid)
{
x=i;
break;
}
}
now=0;
for(int j=1;j<=m;j++)
{
for(int i=1;i<=n;i++)
now+=a[i][j];
if(now>=mid)
{
y=j;
break;
}
}
LL ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
ans+=a[i][j]*(abs(i-x)+abs(j-y));
printf("%lld\n",ans);
}
return 0;
}
暴力:
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const int N=110;
LL a[N][N];
int main()
{
#ifndef ONLINE_JUDGE
// freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
#endif
// ios::sync_with_stdio(false);
int w;
cin>>w;
while(w--)
{
int n,m;
scanf("%d%d",&m,&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%lld",&a[i][j]);
LL ans=1e18;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
LL temp=0;
for(int ii=1;ii<=n;ii++)
for(int jj=1;jj<=m;jj++)
temp+=a[ii][jj]*(abs(i-ii)+abs(j-jj));
ans=min(ans,temp);
}
printf("%lld\n",ans);
}
return 0;
}