首页 > 其他分享 >poj1018(1)

poj1018(1)

时间:2023-05-07 14:32:17浏览次数:45  
标签:poj1018 int 供应商 带宽 枚举 100 设备


其实这道题我也没有完全的弄明白,糊里糊涂就ac了

 

大致题意:

某公司要建立一套通信系统,该通信系统需要n种设备,而每种设备分别可以有m1、m2、m3、...、mn个厂家提供生产,而每个厂家生产的同种设备都会存在两个方面的差别:带宽bandwidths 和 价格prices。

现在每种设备都各需要1个,考虑到性价比问题,要求所挑选出来的n件设备,要使得B/P最大。

其中B为这n件设备的带宽的最小值,P为这n件设备的总价。

    

解题思路:

首先需要明确,要使得B/P最大,自然是要令B尽可能大,P尽可能小。

由于B和P是两个相互制约的变量,而他们又要同时取得尽可能地取极值,那么可以先令其中一个值“暂时固定”下来。

令输入的行数就是设备的种类数,即第i行描述的是第i种设备,及提供第i种设备的厂家的产品信息。

 

枚举+剪枝的做法:

首先B的值肯定是厂家生产的所有设备中的某个带宽值,所以可以枚举所有的带宽,每次枚举B值时,B值就被“暂时固定”了。

其次,记录所选取的B是属于第k种设备的,再从余下的设备中,选取其余n-1种设备各一个,要求所选取的设备的带宽>=B(这是由题意确定的),而价格是要满足带宽的要求下的最小值。

当n种设备都选取后,计算B/P,然后再枚举下一个B,重复上述操作。比较不同的B值所得到的B/P值,选取最大的一个就是答案。

 

剪枝法:

准备工作:

1、输入时先记录:对于每种设备,厂家所提供的最大带宽MaxB[]

2、对所有设备(无论是否同种类)进行升序快排,以带宽为第一关键字,价格为第二关键字,设备所属的种类编号(1~n)为第三关键字。排序后存放在一维数组dev[]

剪枝:

1、  从小到大枚举dev[]中各个设备的带宽作为B值,设总设备数位m,则从1枚举到m-(n-1)。这是因为至少需要选择从枚举位置开始后面的n种设备,m-(n-1)是上限值,即恰好最后n件设备分别为n种设备。

2、  枚举B值的过程中,若发现B值比某种设备的最大带宽更大,则无需继续枚举,输出前面得到的B/P值。这是因为B是所有设备的最小带宽,若出现某个设备的最大带宽比B小,则说明B的选择是不合法的,又dev[]已按B升序排序,后面的B值更大,也不可能成立,因此无需继续枚举。

3、  枚举B值过程中,对于每个B值,在选择其他设备时要记录选取不同种类的设备个数count。最后当count<n时,说明B值位置往后剩余的设备中已无法提供n-1种不同设备,可直接跳出枚举。

 


剪枝2比较难懂,再稍微解释一下,以给的数据为例: 
1 3 
3 100 25 150 35 80 25 
2 120 80 155 40 
2 100 100 120 110

把该组数据升序排序,得到:

B:  80  100  100  120  120  150  155

P:  25  25   100   80  110   35   40

Id:  1   1     3    2    3    1    2


这样当B枚举到150的时候,即B=150,第三个供应商的所有设备都小于150,取任何一个设备都会导致B<150,矛盾。当然大于150的更不用枚举了,直接剪掉。 


package com.njupt.acm;
 import java.io.BufferedReader;
  import java.io.IOException;
  import java.io.InputStreamReader;


  /**
   * 关于题目中的sample input
   * 1 3 
   * 3 100 25 150 35 80 25 
   * 2 120 80 155 40 
   * 2 100 100 120 110
   * 
   * 其实应该有点问题,测试应该按一下输入:
   * 1  (测试用例数)
   * 3  (供应商个数)
   * 3 100 25 150 35 80 25   (第一个供应商提供的设备的情况)
   * 2 120 80 155 40   (第二个供应商提供的设备的情况)
   * 2 100 100 120 110 (第三个供应商提供的设备的情况)
   
   * @author Administrator
   *
   */
  public class POJ1018 {


      double bp = 0;


      public POJ1018() throws NumberFormatException, IOException {
          BufferedReader read = new BufferedReader(new InputStreamReader(
                  System.in));
          
          //记录测试用例的个数
          int t = Integer.parseInt(read.readLine());
          int num;
          int[][] b;
          int[][] p;
          int[] n;
          int bmin;
          int[] bmaxs;//保存最大带宽
          int bmax;
          String[] s;
          int sum;
          int temp;
          for (int i = 0; i < t; i++) {
         //num. 供应商的个数
              num = Integer.parseInt(read.readLine());
              
              //保存设备的带宽
              b = new int[num][];
              
              //保存设备的价格
              p = new int[num][];
              
              n = new int[num];
              
              bmin = Integer.MAX_VALUE;
              bmaxs = new int[num];//默认值全为0
              bmax = Integer.MAX_VALUE;
              for (int j = 0; j < num; j++) {
              
             //将每个供应商提供的设备的情况都保存到s数组里面
                  s = read.readLine().split(" ");
                  
                  //用n数组来保存某个供应商提供的设备的种类数
                  n[j] = Integer.parseInt(s[0]);
                  
                  
                  //用b[]来保存某个供应商提供的各种设备的带宽
                  b[j] = new int[n[j]];
                  
                  //用来保存某个供应商提供的设备的价格
                  p[j] = new int[n[j]];
                  
                  for (int k = 0; k < n[j]; k++) {
                      
                 //k * 2 + 1 , 获得某个供应商提供的某种设备的带宽
                 b[j][k] = Integer.parseInt(s[k * 2 + 1]);
                      
                 /**
                  * if···语句的主要逻辑:
                  * 获得某个供应商所能提供的最大带宽
                  */
                 if (b[j][k] > bmaxs[j]) {
                          
                 bmaxs[j] = b[j][k];
                      }
                  
                  
                  
                 /**
                  * if···语句的主要逻辑;
                  * 获得所有供应商中提供的最小带宽
                  */
                      if (b[j][k] < bmin) {
                          bmin = b[j][k];
                      }
                      
                      //获得某个供应商的某种设备对应的价格
                      p[j][k] = Integer.parseInt(s[k * 2 + 2]);
                  }
                  
                  
              }
              
             
              
              
              /**
               * for循环的主要逻辑:
               * 获得所有供应商中最大带宽中的最小值,保存在bmax中
               */
              for (int j = 0; j < num; j++) {
                  if (bmaxs[j] < bmax) {
                      bmax = bmaxs[j];
                  }
              }
              
              
              
              System.out.println("bmin:" + bmin);
              System.out.println("bmax:" + bmax);
              bp = 0;
              for (int j = bmin; j <= bmax; j++) {//在最小带宽和最大带宽之间做循环
                  
             sum = 0;
                  for (int k = 0; k < num; k++) {//在供应商之间循环
                      temp = Integer.MAX_VALUE;
                      for (int h = 0; h < n[k]; h++) {
                          /**
                           * if···语句的逻辑其实就是求最大B时的最小p
                           */
                     if (b[k][h] >= j && p[k][h] < temp) {
                              
                         //每一个供应商的设备的最小价格
                         temp = p[k][h];
                          }
                      }
                      
                      //获得每个供应商中,当b最大时且p最小时的p的价格之和
                      System.out.println("temp:" +temp);
                      sum += temp;
                  }
                  
                  /**
                   * if···语句的主要逻辑:
                   * 获得最大bp
                   */
                  if ((double) j / sum > bp) {
                  
                 System.out.println( "j:"+j);
                 System.out.println( "sum:"+sum);
                      bp = (double) j / sum;
                      System.out.println("bp:" + bp);
                  }
              }
              System.out.printf("%.3f\n", bp);
          }
      }


      public static void main(String[] args) throws NumberFormatException,
              IOException {
          new POJ1018();
          
         
      } 
 }

标签:poj1018,int,供应商,带宽,枚举,100,设备
From: https://blog.51cto.com/u_5290007/6251960

相关文章