当前位置 - 股票行情交易網 - 股票行情 - 有誰能給我【NOIP2015】《跳石頭》的暴力代碼和二分代碼以及其中算法思想的詳細解釋啊?

有誰能給我【NOIP2015】《跳石頭》的暴力代碼和二分代碼以及其中算法思想的詳細解釋啊?

#include<cstdio>

#include<cstring>

using?namespace?std;

const?int?maxn=50010;

//n,m,L的意義和題目描述中的壹樣,a[]表示每個石頭到起點的距離,方便起見,將終點補充為最後壹塊石頭

int?n,m,L;

int?a[maxn];

//二分了最短跳躍距離?mid之後,開始檢查這個答案mid能不能滿足至多抽走m塊石頭

bool?check(int?mid){

//last表示上壹塊沒有被抽走的石頭離起點的距離

int?last=0,cnt=0;

for(int?i=1;i<=n;i++){

//如果兩點之間的距離比跳躍距離短,那麽就需要把這壹塊石頭拿走,不然的話就可以不用管。

//當然如果i==n也就是終點的時候是不能拿走終點的,但是這個時候拿掉前壹個石頭也壹定能達成目的,所以不管怎樣只需要拿掉壹個石頭。

//如果不用拿掉的話,上壹塊沒有抽走的石頭就是當前這壹塊了。

if(a[i]-last<mid)?cnt++;

else?last=a[i];

}

//如果必須要拿掉的石頭數目<=m個,說明二分出的最短距離可以接受,返回true

if(cnt<=m)?return?true;

return?false;

}

int?main(){

int?ans;

scanf("%d%d%d",&L,&n,&m);

n++;a[n]=L;

for(int?i=1;i<n;i++)?scanf("%d",&a[i]);

int?l=0,r=a[n],mid;

while(r-l>1){

mid=(l+r)>>1;

//如果這個值可以接受,那麽比它小的值都可以接受,二分的下界就可以變成這個新的值

//如果不能接受,那麽比它大的值也不能接受,二分的上界變成這個新的值

if(check(mid))?l=mid;

else?r=mid;

}

//當然如果最後區間還剩下兩個的時候,有可能上界也是可以接受的。[其實這種情況只發生在a[n]為最大距離時]

if(check(r))?ans=r;

else?ans=l;

printf("%d",ans);

return?0;

} 這裏二分思想的使用是因為如果用1表示壹個值可行,0表示壹個值不可行的話。

那麽值域壹定是這樣的:

1111111110000000000

也就是說:比最優值小的壹定都可行,比最優值大的壹定都不可行,這樣的話,我們就可以很快的收斂上下界。使得嘗試的數目變成log2(L)級別。而每次判斷的復雜度是O(n)的,所以得到了滿足時間限制的算法。

其中判斷的部分使用的是貪心的思想,即能放則放,這個思想經常與二分相結合使用。