Ideia central: resposta dicotômica
1. O que é uma resposta dicotômica
Em um intervalo monotônico não decrescente ou monótono não crescente, precisamos encontrar uma resposta para manter a condição do problema.O método mais simples é a enumeração, a complexidade do tempo é O (n) e pode lidar com alguns problemas com dados pequenos Você também pode encontrar esse valor por dicotomia.A complexidade do tempo é O (logn), que é um excelente algoritmo no tempo.
2. Por que essa pergunta pode ser dividida em duas respostas
Como o valor R que procuramos é um número natural, é claro, procuramos em um intervalo crescente, consistente com as características da resposta dicotômica.
3. local específico?
Classificamos a matriz original em ordem crescente para obter o valor máximo.Para que você pense com cuidado, você pode entender que o R que estamos procurando deve estar entre 00 ~ \ max (a [i]) max (a [i]).
Depois, após a classificação l=0,r=a[n]
, você pode verificar se o meio atende à condição todas as vezes.
Se as condições forem atendidas, esse valor poderá ser menor, então r é reduzido para tornarr=mid-1
Pelo contrário, significa que o número é muito grande, então diminua l para fazerl=mid+1
Como testá-lo?
A essência da resposta dicotômica está na função de julgamento
Usamos uma variável para simular o progresso atual da explosão. Contanto que o progresso da explosão não atinja o próximo alcance, precisamos lançar outra. Contanto que o número de vacas lançadas exceda k na pergunta, as condições não serão atendidas.
4. Implementação do código
(Veja notas para detalhes)
#include<cstdio>
#include<iostream>
#include<algorithm>//sort必备
#include<climits>//这个是支持INT_MIN的头文件
using namespace std;
int n,k;
int x[(int)5e4+10];
//皆和题目中意义相同
bool check(int R)
{
int s=0,now=INT_MIN;
/*
s表示已经发射了多少奶牛
now表示当前已爆炸的范围
为什么取INT_MIN呢,因为这样可以保证至少发射一头
*/
for(register int i=1;i<=n;i++)
{
if(now<x[i]-R)
{
//如果当前已爆破的范围小于下一个能触及的范围
s++;
//发射数加1
now=x[i]+R;
//更新当前范围
if(s>k)return false;
//如果超过了限定数,那么就一定pass了
}
}
return true;
//到最后都没pass,说明成功爆破
}
int main()
{
freopen("cpp.in", "r", stdin);
freopen("cpp.out", "w", stdout);
scanf("%d%d",&n,&k);
for(register int i=1;i<=n;i++)
{
scanf("%d",&x[i]);
}
sort(x+1,x+n+1);
int l=0,r=x[n];
while(l<=r)
{
int mid=l+r>>1;
if(check(mid))
{
r=mid-1;
}
else
{
l=mid+1;
}
}
printf("%d\n",l);
//二分模板
return 0;
}
Código AC de mim
#include <iostream>
#include <cstdio>
#include <algorithm>
#define SIZE (int)1e4 * 5 + 10
#define INF 0x3f3f3f3f * 2
using namespace std;
int a[SIZE];
int my_search(const int &, const int &);
bool pan_duan(const int &, const int &, const int &);
int main() {
freopen("cpp.in", "r", stdin);
freopen("cpp.out", "w", stdout);
int n, k;
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
sort(a + 1, a + n + 1);
printf("%d\n", my_search(n, k));
return 0;
}
int my_search(const int &n, const int &k) {
int left = 0, right = a[n];
while (left <= right) {
int mid = (left + right) >> 1;
if (pan_duan(n, k, mid)) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return left;
}
bool pan_duan(const int &n, const int &k, const int &R) {
int num = 0, now = -INF;
for (int i = 1; i <= n; ++i) {
if (a[i] - R > now) {
now = a[i] + R;
++num;
if (num > k) {
return false;
}
}
}
return true;
}