HihoCode-1053-居民迁移

解法:

一开始不会做,看到标签说是贪心加二分忽然就会了,二分是分的是人口最多居住点的人口,检查人口最多的居住点人口为mid是否可行。贪心是如果从左往右循环就尽量把人口往左迁移,如果从右往左循环就尽量把人口往右迁移。

  • 二分 + 贪心
    1053 居民迁移 AC G++ 201ms 7MB
    #include "bits/stdc++.h"
    using namespace std;
    typedef long long LL;
    typedef pair<int, int> PII;
    const int MAXN = 100005;
    PII arr[MAXN];
    int t, n, m;
    bool check(int mid) {
        int k = 0, id = 1;
        for (int i = 1; i <= n; i++) {
            // 第i号居住点的居民已经无法迁移到第id号居住点的情况 
            while (arr[i].first - arr[id].first > m) {
                // 让第i号居住点的居民迁移到下一个居住点,并初始化第id + 1号居住点的人口为0; 
                id++;
                k = 0;
            }
            k += arr[i].second;
            // 因为每个居住点最多住mid人,当k大于mid时,剩下的居民要去下一个居住点 
            while (k > mid) {
                k -= mid;
                id++;
            }
            // 前者表示越出,无第id号居住点;后者表示第i号点的居民无法迁移到第id号点,但是前面的点都满员了; 
            if (id > n || arr[id].first - arr[i].first > m) {
                return false;
            }
         }
         return true;
    }
    int main() {
        scanf("%d", &t);
        while (t--) {
            scanf("%d%d", &n, &m);
            for (int i = 1; i <= n; i++) {
                scanf("%d%d", &arr[i].first, &arr[i].second);
            }
            sort(arr + 1, arr + 1 + n);
            int l = 1, r = 1e9;
            while (l < r - 1) {
                int mid = l + r >> 1;
                if (check(mid)) {
                    r = mid;
                } else {
                    l = mid;
                }
            }
            printf("%d\n", r);
        }
        return 0;
    }

     

posted @ 2019-03-02 10:03  Jathon-cnblogs  阅读(194)  评论(0编辑  收藏  举报