【二分枚举】修补木桶

来源:互联网 发布:网络电视突然连不上网 编辑:程序博客网 时间:2024/04/28 21:39

描述

一只木桶能盛多少水,并不取决于桶壁上最高的那块木板,而恰恰取决于桶壁上最短的那块。

已知一个木桶的桶壁由N块木板组成,第i块木板的长度为Ai。

现在小Hi有一个快捷修补工具,每次可以使用修补工具将连续的不超过L块木板提高至任意高度。

已知修补工具一共可以使用M次(M*L<N),如何修补才能使最短的那块木板最高呢?

注意: 木板是环形排列的,第N-1块、第N块和第1块也被视为连续的。

输入

第1行:3个正整数,N, M, L。分别表示木板数量,修补工具使用次数,修补工具每次可以同时修补的木板数。 1≤N≤1,000,1≤L≤20,M*L<N

第2行:N个正整数,依次表示每一块木板的高度Ai,1≤Ai≤100,000,000

输出

第1行:1个整数。表示使用修补工具后,最短木块的所能达到的最高高度

样例说明

第一个修补工具覆盖[2 3 4]

第二个修补工具覆盖[5 8 1]


样例输入
8 2 38 1 9 2 3 4 7 5
样例输出
7


这题用到二分枚举+贪心的思想。搬一下taosama的代码来,仅作学习保存之用。原文链接:点击打开链接



////  Created by TaoSama on 2016-08-21//  Copyright (c) 2016 TaoSama. All rights reserved.//#pragma comment(linker, "/STACK:102400000,102400000")#include <algorithm>#include <cctype>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <ctime>#include <iomanip>#include <iostream>#include <map>#include <queue>#include <string>#include <set>#include <vector>using namespace std;#define pr(x) cout << #x << " = " << x << "  "#define prln(x) cout << #x << " = " << x << endlconst int N = 1e3 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;int n, m, L;int a[N];bool check(int x) {    vector<int> b(a, a + n);    for(int t = 0; t < n; ++t) {        int bk = b.back(); b.pop_back();        b.insert(b.begin(), bk);        int lft = m, ok = 1;        for(int i = 0; i < n && ok;) {            if(b[i] >= x) ++i;            else {                i += L;                if(--lft < 0) ok = 0;            }        }        if(ok) return true;    }    return false;}int main() {#ifdef LOCAL    freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);//  freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);#endif    ios_base::sync_with_stdio(0);    scanf("%d%d%d", &n, &m, &L);    for(int i = 0; i < n; ++i) scanf("%d", &a[i]);    int l = 1, r = 1e9 + 10, ans = -1;    while(l <= r) {        int m = l + r >> 1;        if(check(m)) ans = m, l = m + 1;        else r = m - 1;    }    printf("%d\n", ans);    return 0;}



0 0
原创粉丝点击