nyoj 586 疯牛(二分+贪心)
生活随笔
收集整理的這篇文章主要介紹了
nyoj 586 疯牛(二分+贪心)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
瘋牛
時間限制:1000?ms ?|? 內存限制:65535?KB 難度:4 描述但是,John的C (2 <= C <= N)頭牛們并不喜歡這種布局,而且幾頭牛放在一個隔間里,他們就要發生爭斗。為了不讓牛互相傷害。John決定自己給牛分配隔間,使任意兩頭牛之間的最小距離盡可能的大,那么,這個最大的最小距離是什么呢? 輸入
第一行:空格分隔的兩個整數N和C
第二行——第N+1行:分別指出了xi的位置
3
題意要表達的是:把C頭牛放到N個帶有編號的隔間里,使得任意兩頭牛所在的隔間編號的最小差值最大。例如樣例排完序后變成1 2 4 8 9,那么1位置放一頭牛,4位置放一頭牛,它們的差值為3;最后一頭牛放在8或9位置都可以,和4位置的差值分別為4、5,和1位置的差值分別為7和8,不比3小,所以最大的最小值為3。
分析:這是一個最小值最大化的問題。先對隔間編號從小到大排序,則最大距離不會超過兩端的兩頭牛之間的差值,最小值為0。所以我們可以通過二分枚舉最小值來求。假設當前的最小值為x,如果判斷出最小差值為x時可以放下C頭牛,就先讓x變大再判斷;如果放不下,說明當前的x太大了,就先讓x變小然后再進行判斷。直到求出一個最大的x就是最終的答案。
cpp:
#include <stdio.h> #include <stdlib.h> #define Max_size 100020 int x[Max_size]; int N,C; int com(const void *a,const void *b)//排序 {return *(int *)a-*(int *)b; } bool Judge(int v) {//v表示兩牛之間最小的距離值int i;int num=0;//房子編號int t;for(i=1;i<C;i++)//對牛計數{t=num+1;while(t<N&&x[t]-x[num]<v)//t跳出時 t==N說明列舉了 num之后的所有房子都無法滿足兩房子之間距離<=v值t++;//反之,則說明找到了滿足條件的房子if(t==N)return false;num=t;}return true; } int main() {int i;int bottom,top;int mid;while(~scanf("%d%d",&N,&C)){for(i=0;i<N;i++)scanf("%d",x+i);qsort(x,N,sizeof(x[0]),com);//因為每個房間的坐標是混亂的,所以對每個房間的坐標進行小到大排序bottom=0;top=(x[N-1]-x[0])*2;//確定上界和下界while(top-bottom>1){mid=(top+bottom)/2;if(Judge(mid))bottom=mid;//mid值能滿足條件 說明答案的區間為[mid,top)else top=mid;//mid 值不能滿足條件 說明答案的區間為(bottom,mid)}printf("%d\n",bottom);}return 0; }#include<stdio.h> #include <stdlib.h> int cmp(const void*a,const void *b) {return *(int *)a-*(int *)b; } int a[1000001]; int main() {int i,c,h,sum;while(scanf("%d%d",&h,&c)!=EOF){for(i=0;i<h;i++)scanf("%d",&a[i]);qsort(a,h,sizeof(a[0]),cmp);int max=a[h-1]-a[0];//二分搜索的范圍,這里Max是兩頭牛相距的最大范圍 int min=0,mid;while(max>=min){mid=(min+max)/2;//截取中間的這個點 int m=1,n=0;sum=0;while(m<h){if(a[m]-a[n]>=mid)//領M個元素與第N個元素比較,如果大于這個等于Mid,說明這個距離可以放牛, { // 然后把N的值改變,n=m,讓下一個m++元素與這個n比較, sum++; //同時記錄符合這個距離的情況有幾種,sum++; n=m;}m++;}if(sum>=c-1)//如果這種情況是大于c-1頭牛的,說明答案在 【mid+1,max】中 {min=mid+1;}else //如果這種情況是小于c-1頭牛的,說明答案在 【min,mid-1】中 {max=mid-1;}}printf("%d\n",min-1); }return 0; }
這個是貪心和二分.二分查找又是折半查找,首先,元素是升序排列,每次查找中間元素和待查找元素進行比較,如果相同,就返回中間元素的位置值,如果不相同且中間元素大于待查找元素就從右邊開始,如果不相同且中間元素小于待查找元素就從左邊開始,適用于不經常變動而且查找頻繁的有序列表。
總結
以上是生活随笔為你收集整理的nyoj 586 疯牛(二分+贪心)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql中修改表字段的类型长度_mys
- 下一篇: CPropertySheet 与CPro