荆棘林的最优砍断计划
阿里算法岗 0530笔试 第一题
题目内容
林中共有 n n n 株荆棘,第 i i i 株的坚硬度为 a i a_i ai,宝刀的初始锋利度为 K K K。拉布可以选择任意数量的荆棘,每株至多尝试一次,并以任意顺序依次尝试砍断。每次尝试遵循以下规则:
- 若当前锋利度 K K K 满足 K ≥ a i K \ge a_i K≥ai,则该荆棘被成功砍断。
- 无论成功与否,每次尝试结束后锋利度 K K K 都会永久减少 1 1 1。
拉布可以放弃任意荆棘(放弃不消耗锋利度)。请计算在最优策略下,最多能成功砍断多少株荆棘。
输入描述
每个测试文件包含多组测试数据。第一行输入一个整数 T T T( 1 ≤ T ≤ 10 5 1 \le T \le 10^5 1≤T≤105)表示数据组数,每组测试数据描述如下:
每组输入一行两个整数 n , K n, K n,K( 1 ≤ n ≤ 2 × 10 5 1 \le n \le 2 \times 10^5 1≤n≤2×105, 1 ≤ K ≤ 10 9 1 \le K \le 10^9 1≤K≤109)。
接下来一行输入 n n n 个整数 a 1 , a 2 , ... , a n a_1, a_2, \dots, a_n a1,a2,...,an( 1 ≤ a i ≤ 10 9 1 \le a_i \le 10^9 1≤ai≤109)。
保证所有测试数据的 n n n 之和不超过 2 × 10 5 2 \times 10^5 2×105。
输出描述
对于每组测试数据,输出一个整数,表示在最优策略下最多能成功砍断的荆棘数量。
样例1
输入
3
5 5
2 1 4 10 3
2 1
10 10
3 3
3 3 3
输出
4
0
1
题解和思路
思路
实现思路:贪心
- 按照
优先砍锋利度高的,能砍就砍的策略去计算数量。 - 将荆棘降序排序,从大到小进行扫描,如果
a[i] <= k,更新ans++, k-- - 最终
ans就是能砍的最大数量。
C++
cpp
#include<bits/stdc++.h>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T--) {
int n,k;
cin >> n >> k;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
// 排序
sort(a.begin(), a.end());
int count = 0;
for (int i = n - 1; i >= 0; i--) {
// 能砍断就砍
if (a[i] <= k) {
k--;
count++;
}
}
cout << count << endl;
}
return 0;
}
Java
java
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
while (T-- > 0) {
int n = sc.nextInt();
int k = sc.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = sc.nextInt();
}
// 排序
Arrays.sort(a);
int count = 0;
for (int i = n - 1; i >= 0; i--) {
// 能砍断就砍
if (a[i] <= k) {
k--;
count++;
}
}
System.out.println(count);
}
sc.close();
}
}
python
python
T = int(input())
for _ in range(T):
n, k = map(int, input().split())
a = list(map(int, input().split()))
# 排序
a.sort()
count = 0
for i in range(n - 1, -1, -1):
# 能砍断就砍
if a[i] <= k:
k -= 1
count += 1
print(count)
print(count)
Javascript
js
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
const lines = [];
rl.on('line', line => {
lines.push(line);
});
rl.on('close', () => {
let idx = 0;
const T = Number(lines[idx++]);
for (let t = 0; t < T; t++) {
const [n, k0] = lines[idx++].split(' ').map(Number);
let k = k0;
const a = lines[idx++].split(' ').map(Number);
// 排序
a.sort((a, b) => a - b);
let count = 0;
for (let i = n - 1; i >= 0; i--) {
// 能砍断就砍
if (a[i] <= k) {
k--;
count++;
}
}
console.log(count);
}
});
Go
go
package main
import (
"fmt"
"sort"
)
func main() {
var T int
fmt.Scan(&T)
for T > 0 {
T--
var n, k int
fmt.Scan(&n, &k)
a := make([]int, n)
for i := 0; i < n; i++ {
fmt.Scan(&a[i])
}
// 排序
sort.Ints(a)
count := 0
for i := n - 1; i >= 0; i-- {
// 能砍断就砍
if a[i] <= k {
k--
count++
}
}
fmt.Println(count)
}
}