小白月赛22 G : 仓库地址

G : 仓库地址

考察点: 二维中位数
坑点 :  做就 OK

析题得侃:

我们发现 x 和 y 是相互独立的,也就是说先移动 x 或者先移动 y
都是可以到达一个点的,所以我们可以先找到 横坐标的 中位数,
在找到 纵坐标的中位数,然后将这个点带入计算即可。

所有数与中位数的绝对差之和最小。

Code :

#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 105;
typedef long long LL;

int a[maxn][maxn];

int T,n,m,x,y;
LL res = 0;

int main(void) {
	void midNum();
	scanf("%d",&T);
	while(T --) {
		res = 0;
		scanf("%d%d",&m,&n);
		for(int i = 1; i <= n; i ++) {
			for(int j = 1; j <= m; j ++) {
				scanf("%d",&a[i][j]);
				res += a[i][j];
			}
		}
		x = 0,y = 0;
		midNum();
		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));
			}
		}
		cout << ans << endl;
	} 
	return 0;
} 

void midNum() {
	LL ans = (res + 1) >> 1;
	LL sum = 0;
        // 寻找横坐标的 中位数
	for(int i = 1; i <= n; i ++) {
		for(int j = 1; j <= m; j ++) {
			sum += a[i][j];
		}
		if(sum >= ans) {
			x = i;
			break;
		}
	}
	sum = 0;
        // 寻找纵坐标的中位数
	for(int j = 1; j <= m; j ++) {
		for(int i = 1; i <= n; i ++) {
			sum += a[i][j];
		}
		if(sum >= ans) {
			y = j;
			break;
		}
	}
	return ;
}
posted @ 2020-02-23 22:48  IceSwords  阅读(148)  评论(0编辑  收藏  举报