小白月赛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 ;
}

猜你喜欢

转载自www.cnblogs.com/prjruckyone/p/12354886.html
今日推荐