描述
一只木桶能盛多少水,并不取决于桶壁上最高的那块木板,而恰恰取决于桶壁上最短的那块。
已知一个木桶的桶壁由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 3 8 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 << endl
const 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;
}