独木舟(贪心)

xiaoxiao2021-02-28  124

独木舟问题   n个人,已知每个人体重。独木舟承重固定,每只独木舟最多坐两个人,可以坐一个人或者两个人。显然要求总重量不超过独木舟承重,假设每个人体重也不超过独木舟承重,问最少需要几只独木舟? n个人,已知每个人体重,独木舟承重固定,每只独木舟最多坐两个人,可以坐一个人或者两个人。显然要求总重量不超过独木舟承重,假设每个人体重也不超过独木舟承重,问最少需要几只独木舟? 分析:  一个显然的策略是按照人的体重排序。 极端化贪心策略,最重的人要上船——如果最重的人和最轻的人体重总和不超过船的承重,则他们两个占用一条船。否则(因为假设最重的人的体重也不超过船的承重了),最重的人单独占一条船。转变为(n – 1)或者(n – 2)的问题了。   关键在于这种贪心策略是正确的。我们可以证明,最优解也可以变为这种策略。 (1) 假设最重的人和最轻的人的体重和超过了船的承重,那么最优解中,显然也是最重的人单独占一条船,所以这种情况下最优解和贪心策略是相同的。 (2) 假设最重的人和最轻的人的体重和没超过船的承重。 (2.1)如果最优解中,最重的人单独占用一条船,则可以把最轻的人也放上去,这样最优解用的船数不增加。如果最轻的人占用一条船,同样我们可以把最重的人放上去,最优解船数不增。 (2.2) 如果最优解中最重的人x和x’占用一只船(x, x’),而最轻的人y和y’占用一只船(y, y’) 我们换成(x, y) (x’,y’) (x, y)显然没超过船的承重——因为我们假设就是如此。关键看(x’, y’)。 x’ + y’<= x’ + x 因为(x’, x)没超重,所以(x’,y’)也合法。所以换一下,最优解船数也不增。 这样我们就证明了如果可能把最重的人和最轻的人放在一条船上,不会影响最优解。 反复应用这个策略,就可以把n降低为(n – 1)或者(n – 2)个人的规模,从而解决这个问题。 最后,我们来提供输入输出数据,由你来写一段程序,实现这个算法,只有写出了正确的程序,才能继续后面的课程。   输入 第一行包含两个正整数n (0<n<=10000)和m (0<m<=2000000000),表示人数和独木舟的承重。 接下来n行,每行一个正整数,表示每个人的体重。体重不超过1000000000,并且每个人的体重不超过m。 输出   一行一个整数表示最少需要的独木舟数。   输入示例 3 6 1 2 3 输出示例 2 这道题不难,贴出来是因为这些代码是我自己写出来的,很有成就感   // #include <stdio.h> #include <string.h> #include <algorithm>   using  namespace  std ;   int  n ,  m ; int  i ,  j ; int  weight [ 10000+10 ] ; int  ans = 0 ;   void  solve ( int  x ,  int  y )//递归函数 {      if ( weight [ x ]  +  weight [ y ]  <=  m  &&  x <= y )//此处一定要注明递归跳出的条件      {          ans ++ ;          solve ( x +1 ,  y -1 ) ;      }         else  if ( weight [ x ]  +  weight [ y ]  >  m  &&  x <= y )      {          ans ++ ;          solve ( x ,  y -1 ) ;      } } int  main ( ) {      scanf ( "%d %d" ,  & n ,  & m ) ;      for ( i = 0 ;  i < n ;  i ++ )      {          scanf ( "%d" ,  & weight [ i ]) ;      }      sort ( weight ,  weight + n ) ;      solve ( 0 ,  n -1 ) ;      printf ( "%d\n" ,  ans ) ;      return  0 ; }           XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 上一屏 提交代码 回到教程
转载请注明原文地址: https://www.6miu.com/read-41680.html

最新回复(0)