acwing 105 七夕祭

74 阅读1分钟

题目链接:acwing 105 七夕祭

前置题目:acwing 104 货仓选址acwing 122 糖果传递

本题和糖果传递问题是相同的思路,区别就是把一维问题变成了二维问题,只需要对行和列分别按“糖果传递”问题的思路求解即可。

#include<cstdio>
#include<algorithm>
#include <vector>
#define PII pair<int, int>
using namespace std;
// 【注】行上的交换行为不会对列上的个数产生任何影响

int n, m, T;
vector<PII> a;

long long cal(int x) {
    int len = x == 1 ? m : n;
    vector<int> b(len + 2, 0);
    for (auto p : a) { // 把行/列压缩到一维(像串糖葫芦),然后就是“货仓选址”问题
        if (x == 0) b[p.first]++;
        else b[p.second]++;
    }
    int avg = T / len;
    for (int i = len; i >= 2; i--)
        b[i] = b[i + 1] + b[i] - avg;
    b[1] = 0;
    sort(b.begin() + 1, b.begin() + len + 1);
    int mid = (len >> 1) + 1;
    long long res = 0;
    for (int i = 1; i <= len; ++i) res += abs(b[mid] - b[i]);
    return res;
}

int main() {
    scanf("%d %d %d", &n, &m, &T);
    int t1, t2;
    for (int i = 0; i < T; ++i) {
        scanf("%d %d", &t1, &t2);
        a.push_back({t1, t2});
    }
    long long res = 0;
    if (T % n == 0 && T % m == 0) {
        res = cal(0) + cal(1); // 先后计算行/列的“货仓选址”问题
        printf("both %lld", res);
    } else if (T % n == 0) {
        res = cal(0);
        printf("row %lld", res);
    } else if (T % m == 0) {
        res = cal(1);
        printf("column %lld", res);
    } else {
        printf("impossible");
    }
    return 0;
}