蓝桥杯-PREV45-图形排版

这是2017年蓝桥杯C组C++的压轴题,拿到之后没什么想法。但是蓝桥杯有部分分。所以直接敲了个大暴力提交上去过了一半的数据。后来想到了DP,但是没能实现出来,感觉还是有问题的。后来看了解题视频发现是预处理。

  • 大暴力
    图形排版 739B C++ 运行超时 50 运行超时 1.585MB
    #include "cstdio"
    #include "algorithm"
    using namespace std;
    typedef pair<int, int> PII;
    const int MAXN = 100005;
    const int INF = 0x3f3f3f3f;
    PII arr[MAXN];
    int n, m;
    int check(int id) {
        int k = n, cnt = 0, h = 0;
        for (int i = 0; i < m; i++) {
            if (i == id) {
                continue;
            }
            if (k > arr[i].first) {
                k -= arr[i].first;
                h = max(h, arr[i].second);
            } else {
                h = max(h, (arr[i].second * k - 1) / arr[i].first + 1);
                k = n;
                cnt += h;
                h = 0;
            }
        }
        if (h != 0) {
            cnt += h;
        }
        return cnt;
    }
    int main() {
        scanf("%d%d", &n, &m);
        for (int i = 0; i < m; i++) {
            scanf("%d%d", &arr[i].first, &arr[i].second);
        }
        int mn = INF;
        for (int i = 0; i < m; i++) {
            mn = min(mn, check(i));
        }
        printf("%d\n", mn);
        return 0;
    }

    比赛想不到后面的方法感觉这个方法也够了,毕竟我做到最后一题的时候时间已经不多了。

  • 预处理
    图形排版 1.300KB C++ 正确 100 62ms 2.070MB
    #include "cstdio"
    #include "iostream"
    #include "algorithm"
    using namespace std;
    typedef pair<int, int> PII;
    const int MAXN = 100005;
    const int INF = 0x3f3f3f3f;
    // 存n张图片,first为宽,second为高 
    PII arr[MAXN];
    // 预处理,f[i]表示第i张图到第n张图需要的高度 
    int f[MAXN];
    int n, m;
    // Add用于往一个行里加入第k张图片 
    void Add(PII* p, int k) {
        if (p->first + arr[k].first < m) {
            p->first += arr[k].first;
            p->second = max(p->second, arr[k].second);
        } else {
            p->second = max(p->second, (arr[k].second * (m - p->first) - 1) / arr[k].first + 1);
            p->first = m;
        }
    }
    int getF(PII p, int k) {
        while (k <= n && p.first < m) {
            Add(&p, k);
            k++;
        }
        // 因为已经求出f[k]了,所以k后面就不用再算了; 
        return p.second + f[k];
    }
    int main() {
        scanf("%d%d", &m, &n);
        for (int i = 1; i <= n; i++) {
            scanf("%d%d", &arr[i].first, &arr[i].second);
        }
        for (int i = n; i >= 1; i--) {
            f[i] = getF(make_pair(0, 0), i);
        }
        // pre表示在now表示的行上面已经存在的高度; 
        int pre = 0, res = INF;
        // now表示当前正在填充的行 
        PII now = make_pair(0, 0);
        for (int i = 1; i <= n; i++) {
            res = min(res, pre + getF(now, i + 1));
            Add(&now, i);
            if (now.first == m) {
                pre += now.second;
                now.first = now.second = 0;
            }
        }
        printf("%d\n", res);
        return 0;
    }

     

posted @ 2019-03-21 22:48  Jathon-cnblogs  阅读(811)  评论(3编辑  收藏  举报