二分最佳化—無限逼近求解

來源:互聯網
上載者:User

摘要:

通過對一個問題兩種解法分析,揭示了二分逼近求解的精妙之處

 

問題描述如下:

給定N( 1 <= N <= 100000) 個數,求往N個中數取C(2 <=C< N)個數,使C個數之間兩兩之差的最小值在同類情況下是最大的。

 

sample:

 N = 5, C = 3;

N個數為:  1,2,8,4,9

解的情況為: 1,8,4; 最小值為 3。

其他同類情況可以為1,2,9 or 1,2,4 etc,但是其最小值均為1,不是最佳解。

 

第一種解法:

對 N個數進行子集樹回溯,然後對每種情況挑出最小值,然後再和maxnum比較,最後出結果。但是這種解法不好地方在於N的個數太大,深搜會出現runtime error。

 

第二種解法:

在0----num[n-1]之間取一值, 假設其為最佳解,和N個數的兩兩值差進行比較,再統計有多少個值差在假設值之上,若統計值大於等於C則把假設值降低,再進行判斷,反之則提高數值.在提高和降低假設值的過程需要用到二分尋找.所需要的時間為nlogn,遠遠高效於回溯的2^n

 

相關代碼如下:

 

//代碼粘得比較不可觀;
#include <stdio.h>

int a[100000];
int n,m;

bool find(int v)
{
  int pre=a[0],c=0;
   
 for(int i=1;i<n;i++)
 {
      if(a[i]-pre>=v)
     {
           c++;
           pre=a[i];  
     }   
  }  

  if(c>=m)
 return true;
 else
 return false;
}

int cmp(const void *x,const void *y)
{
      return *(int *)x-*(int *)y;  
}

int main()
{
    //freopen("in.txt","r",stdin);
    scanf("%d%d",&n,&m);
    m--;
   
 for(int i=0;i<n;i++)
 {
     scanf("%d",&a[i]);
 }

    qsort(a,n,sizeof(a[0]),cmp);  
   
    int left=0,right=a[n-1],mid;
   
 while(left<=right)
 {
      mid=(left+right)/2;
   
      if(find(mid))
          left=mid+1;
      else
          right=mid-1;  
  }  
   
      printf("%d/n",left-1);
  return 0;
}

 相關的二分法練習如下:

http://acm.pku.edu.cn/JudgeOnline/problem?id=3388
http://acm.pku.edu.cn/JudgeOnline/problem?id=2456
http://acm.zju.edu.cn/show_problem.php?pid=2002

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.