这道题在考试时二分答案写炸了,结果得了20分。。。。。同学有用贪心写的(对,贪心!!)都得了30,我感到了深深的恶意。这段时间在忙转语言,现在重新整理一下NOIP的题。
题目来源:vijos
题目如下:
组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳 跃距离尽可能长。由于预算限制,组委会至多从起点和终点之间移走 M 块岩石(不能 移走起点和终点的岩石)。
格式
输入格式
输入第一行包含三个整数 L,N,M,分别表示起点到终点的距离,起点和终 点之间的岩石数,以及组委会至多移走的岩石数。
接下来 N 行,每行一个整数,第 i 行的整数 Di
(0<Di<L
)表示第 i
块岩石与 起点的距离。这些岩石按与起点距离从小到大的顺序给出,且不会有两个岩石出现在同 一个位置。
输出格式
输出只包含一个整数,即最短跳跃距离的最大值。
样例1
样例输入1[复制]
25 5 2 2 11 14 17 21
样例输出1[复制]
4
限制
对于20%的数据,0≤M≤N≤10
。
对于50%的数据,0≤M≤N≤100
。
对于100%的数据,0≤M≤N≤50000
,1≤L≤1000000000
。
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #include <iostream> 5 6 using namespace std; 7 8 int a[50010]; 9 int n,m; 10 11 int ok(int mid) //判断当前答案是否可行 12 { 13 int i,head=0,count=0; //head记录上一个可行的点,count计数 14 for(i=1;i<=n;i++) 15 { 16 if(a[i]-head<mid) 17 count++; 18 else head=a[i]; 19 } 20 if(count<=m) return 1; //如果当前数量小于等于要求(可行),则返回1 21 else return 0; //否则返回0 22 } 23 24 int main() 25 { 26 int l,max=0,ans; 27 a[0]=0; 28 29 scanf("%d%d%d",&l,&n,&m); 30 if (m==0) { cout<<l; return 0;} 31 for (int i=1; i<=n; i++) 32 scanf("%d",&a[i]); 33 n++; 34 a[n]=l; 35 int head=1; 36 int tail=l; 37 while(head<=tail) //head,head记录当前二分的区间 38 { 39 if(ok((head+tail)/2)) 40 head=(head+tail)/2+1; 41 else tail=(head+tail)/2-1; 42 ans=(head+tail)/2; 43 } 44 cout <<ans; 45 return 0; 46 }
时间: 2024-10-21 23:07:22