《算法竞赛·快冲300题》将于2024年出版,是《算法竞赛》的辅助练习册。
所有题目放在自建的OJ New Online Judge。
用C/C++、Java、Python三种语言给出代码,以中低档题为主,适合入门、进阶。
“ 松鼠与栗子” ,链接: http://oj.ecustacm.cn/problem.php?id=1852
题目描述
【题目描述】 现在有m棵栗子树,n只松鼠在等待栗子下落。
第i棵树的第一个栗子在t[i],之后每p[i]秒都掉落一个。
现在松鼠们希望最终能获得k个栗子,每只松鼠将选择一棵栗子树等待。
不考虑松鼠移动到每棵树的时间,只考虑等待时间。
请求出最优情况下的最少的等待时间,即松鼠选择最优情况下的n个栗子树进行等待,等待时间最小是多少。
【输入格式】 第一行为正整数m,n,k。1≤n≤m≤10000,1≤k≤10^7。
第二行包含m个整数表示t[i]。
第三行包含m个整数表示p[i],1≤t[i],p[i]≤100。
【输出格式】 输出一个数字表示答案。
【输入样例】
样例1:
3 2 5
5 1 2
1 2 1
样例2:
3 2 5
5 1 2
1 1 1
【输出样例】文章来源:https://www.toymoban.com/news/detail-679941.html
样例1:
4
样例2:
3
题解
这是一道很直接的二分题。等待时间越长,掉落栗子越多,所以等待时间对应的栗子数量是单调递增的,可以用二分法。猜一个最小等待时间x,用二分法找到x。
用check(x)函数判断x时间是否掉落超过k个栗子。首先算出m颗树在x秒时一共掉落多少个栗子, 若栗子总数少于k, 返回false;如果超过k个,对m棵树掉落的栗子排序后,选择前n个与k比较。
【重点】 二分 。文章来源地址https://www.toymoban.com/news/detail-679941.html
C++代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e4 + 10;
int t[N], p[N];
int num[N];
int n, m, k;
bool check(int x){
for(int i = 1; i <= m; i++) {
if(x >= t[i]) num[i] = (x - t[i]) / p[i] + 1;
else num[i] = 0;
}
long long sum = 0;
sort(num + 1, num + 1 + m, greater<int>()); //从大到小排序
for(int i=1; i<=n && i<=m; i++) sum += num[i];
return sum >= k;
}
int main(){
cin >> m >> n >> k;
if(n > m) n = m;
for(int i=1; i<=m; i++) cin >> t[i];
for(int i=1; i<=m; i++) cin >> p[i];
int L=0, R=1e9, ans=0;
while(L <= R){
int mid = (L + R) >> 1;
if(check(mid)) ans = mid, R = mid - 1;
else L = mid + 1;
}
cout<<ans<<endl;
return 0;
}
Java代码
import java.util.*;
public class Main {
static int[] t = new int[10010];
static int[] p = new int[10010];
static int[] num = new int[10010];
static int n, m, k;
public static boolean check(int x) {
for (int i = 1; i <= m; i++) {
if (x >= t[i]) num[i] = (x - t[i]) / p[i] + 1;
else num[i] = 0;
}
long sum = 0;
Arrays.sort(num, 1, m + 1);
for (int i=1; i<=n && i<=m; i++) sum += num[m - i + 1];
return sum >= k;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
m = sc.nextInt();
n = sc.nextInt();
k = sc.nextInt();
if (n > m) n = m;
for (int i = 1; i <= m; i++) t[i] = sc.nextInt();
for (int i = 1; i <= m; i++) p[i] = sc.nextInt();
int L = 0, R = 1000000000, ans = 0;
while (L <= R) {
int mid = (L + R) >> 1;
if (check(mid)) { ans = mid; R = mid - 1; }
else L = mid + 1;
}
System.out.println(ans);
sc.close();
}
}
Python代码
t = [0] * (10010)
p = [0] * (10010)
num = [0] * (10010)
def check(x):
for i in range(1, m + 1):
if x >= t[i]: num[i] = (x - t[i]) // p[i] + 1
else: num[i] = 0
num.sort(reverse=True)
sum = 0
for i in range(1, n+1 if n<=m else m+1): sum += num[i]
return sum >= k
m, n, k = map(int, input().split())
t[1:] = [int(x) for x in input().split()]
p[1:] = [int(x) for x in input().split()]
L, R, ans = 0, 1000000000, 0
while L <= R:
mid = (L + R) // 2
if check(mid):
ans = mid
R = mid - 1
else: L = mid + 1
print(ans)
到了这里,关于《算法竞赛·快冲300题》每日一题:“松鼠与栗子”的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!