• POJ 1018 【枚举+剪枝】.cpp


    题意:

      给出n个工厂的产品参数带宽b和价格p,在这n个工厂里分别选1件产品共n件,使B/P最小,其中B表示n件产品中最小的b值,P表示n件产品p值的和。

      输入 iCase n

        表示iCase个样例n个工厂
        m1 p1 b1 p2 b2..pm1 bm1 //第一个工厂有m1个同种类不同参数的产品,每一个产品的参数分别是p1 b1 p2 b2
        m2 p1 b1 p2 b2..pm2 bm2
        ...
        mn p1 b1 p2 b2..pmn bmn

         

    思路:

      排序,先把b从小到大排序,然后把p从小到大排序,最后让第几个工厂的序号从小到大排序

      排完后就可以直接枚举了,枚举bi,固定了bi之后就枚举pj,取每一个工厂里满足bj比bi大的就加起来,然后计算哪一个值最大..

    Tip:

    其中有一些优化就是剪枝:

        ①. 因为最后肯定要有n个bj比bi大,所以bi枚举到sum-(n-1)就可以了,sum表示总共有多少个产品..

        ②. 如果枚举到bi比某一个公司的所有产品的b都大的时候,就不用往后枚举了,因为产品是按b排过序的,题目要求n-1个公司里面选取的b都要比当前bi大,既然当前bi比某一个公司的所有b都大了,则该公司无法选取符合条件的产品,而后面产品b都比bi大,就跟不可能选取到符合条件的产品了,所以就可以直接break;

        ③. 如果枚举到某一个bi的时候,bj比bi大的公司个数不满n个的话bi后面的b也可以不枚举了,原因同上..

      

    Code:

     1 #include <stdio.h>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 const int MAXN = 110;
     7 
     8 struct Div
     9 {
    10     int id;
    11     int p;
    12     int b;
    13 }_div[MAXN*MAXN];
    14 int maxB[MAXN];
    15 
    16 int cmp(Div a, Div b)
    17 {
    18     if (a.b != b.b) return a.b < b.b;
    19     else if (a.p != b.p) return a.p < b.p;
    20     else return a.id < b.id;
    21 }
    22 
    23 
    24 int main()
    25 {
    26    // freopen("in.txt", "r", stdin);
    27     int iCase, n, m, sum;
    28     //int vis;
    29     bool vis[MAXN];
    30     double ans;
    31     bool flag;
    32     scanf("%d", &iCase);
    33     while (iCase--) {
    34         sum = ans = 0;
    35         memset(maxB, 0, sizeof(maxB));
    36         flag = true;
    37 
    38         scanf("%d", &n);
    39         for (int i = 0; i < n; ++i) {
    40             scanf("%d", &m);
    41             while (m--) {
    42                 scanf("%d %d", &_div[sum].b, &_div[sum].p);
    43                 maxB[i] = max(maxB[i], _div[sum].b);
    44                 _div[sum++].id = i;
    45             }
    46         }
    47 
    48         sort(_div, _div+sum, cmp);
    49 
    50         for (int i = 0; i < sum-(n-1); ++i) {
    51             int P = _div[i].p;
    52             int count = 1;
    53        //    vis = (1<<n)-1;
    54          //   vis ^= (1<<_div[i].id);
    55             memset(vis, false, sizeof(vis));
    56             vis[_div[i].id] = true;
    57             for (int j = i+1; j < sum; ++j)
    58            //     if (vis & (1<<_div[j].id)) {
    59                 if (!vis[_div[j].id]) {
    60                     if (maxB[_div[j].id] < _div[i].b) {
    61                         flag = false;
    62                         break;
    63                     }
    64                     P += _div[j].p;
    65                     //vis ^= (1<<_div[j].id);
    66                     vis[_div[j].id] = true;
    67                     count++;
    68                 }
    69             if (count < n || !flag) break;
    70             ans = max(ans, (double)_div[i].b/P);
    71         }
    72         printf("%.3lf
    ", ans);
    73     }
    74     return 0;
    75 }
    View Code

    链接:http://poj.org/problem?id=1018

  • 相关阅读:
    【Hadoop】MapReduce自定义分区Partition输出各运营商的手机号码
    【Hadoop】Hadoop的数据压缩方式
    【Java】生成随机的手机号码并输出到文件
    【Java】递归删除目录以及文件
    【Hadoop】单机、伪分布式、完全分布式集群搭建
    【Linux】常用基础命令
    【Web】jquery合并单元格
    【PHP】PHPStorm中文乱码解决方式
    【DataBase】mysql连接错误:Cannot get hostname for your address
    【.NET】Browser Link: Failed to deserialize JSON in Browser Link call
  • 原文地址:https://www.cnblogs.com/Griselda/p/3204332.html
Copyright © 2020-2023  润新知