ms不但是微软还是貌似

 

poj1018 Communication System

总结 :

这个题目思路倒是老早就想起来了,但是实现搞得我心力交瘁阿,最终还是用c++完成的,否则要是用c实现的话,一定会写出来一坨屎一样的代码出来。

题目大意:

 

1 
3 <==三种设备
3 100 25 150 35 80 25 <==第一种设备3个供货商,他们提供的设备的带宽和价格依次排列
2 120 80 155 40 <==同上
2 100 100 120 110 <==同上

 

要用n种(示例中n=3)设备构建一个系统,每个设备有带宽和价格两个属性,而且每种设备都有好多个不一样的供货商,他们提供的设备虽然一样起作用,但是带宽和价格是不同的。

目的就是求出全局带宽(设备中的最小带宽)尽可能大同时总价尽可能小。

算法

算法类似背包问题,按设备依次枚举所有可能全局带宽带所能获得价格最小值。

定义数组 f[i][j], i 取从 0 到 n-1,j 用来枚举所有的可能的全局带宽。f[i][j] 就保存了讨论前 i 种设备的时候,全局带宽 j 所能达到的总价最小值,拗口。。。

 那么,每计算一种设备要考虑3种情况,

第一种是在前一次能达到的全局带宽 j,这次也可能能达到,当然前提是有带宽 >= j的设备

          if f[i - 1][j] is inited,f [i - 1][j] += min{price{k} }, bandwidth(k) >= j

第二种是将那些再次出现的全局带宽进行初始化,

        


我被打败了,太佩服写算法导论的大牛了,那么复杂的算法也能说明白

 

输入数据

1 3 
3 100 25 150 35 80 25
2 120 80 155 40
2 100 100 120 110
 这是我的debug输出,看这个比较明白。

(80, 25) (100, 25) (120, 0) (150, 35) (155, 0) //注意已经删除重复并且排序

(80, 65) (100, 65) (120, 115) (150, 75) (155, 0)
(80, 165) (100, 175) (120, 185) (150, 0) (155, 0)

我用debug(i,j),input(i,j)表示dubug矩阵和input矩阵的元素。

 1. 对于debug(1, j)就是使用input(1, j)初始化,例如input(1,1):(100,25),我们就知道只考虑第一种设备的时候,带宽100是有可能的,价格是25

2. debug(2,1)和debug(2,2)计算过程类似,首先我们知道debug(1,1)和debug(1,2)是有值的,并且input(2,1)和input(2,2)的带宽都要比他大,那么我们只需要从input(2,1)和input(2,2)这两个设备中选一个便宜的加上即可<<===对比debug(3,4)===>>对于debug(3,4)虽然debug(2,4)有值,但是我们发现第三种设备的带宽只有100和120两种选择,都比debug(3,4)的带宽150小,那么选择到第三种设备的时候就不可能有一种方案达到带宽150

 3. debug(2,3)在debug(1,3)是没有值的,但是有输入input(2,1)的带宽是120,所以可以对其进行初始化。怎么初始化呢?我们要看到debug(1,4),debug(1,5)都是带宽比120大,从他们中选小的加上即可

  1 #include <cstdio>
  2 #include <cstring>
  3 
  4 class device_node
  5 {
  6 public:
  7     int b;
  8     int p;
  9 
 10     device_node(): b(0), p(0){}
 11     device_node(int _b, int _p): b(_b), p(_p){}
 12     device_node& operator=(const device_node &right)
 13     {
 14         b = right.b;
 15         p = right.p;
 16         return *this;
 17     }
 18 };
 19 
 20 class devices
 21 {
 22 private:
 23     device_node *array;
 24     int counter;
 25     int num;
 26 
 27 public:
 28     devices(): counter(0), num(100)
 29     {
 30         array = new device_node[102];
 31     }
 32     devices(int _num): counter(0), num(_num)
 33     {
 34         array = new device_node[num + 2];
 35     }
 36     ~devices()
 37     {
 38         delete[] array;
 39     }
 40     void init()
 41     {
 42         counter = 0;
 43         memset(array, 0sizeof(device_node) * (num + 2));
 44     }
 45     void append(device_node &node, bool multi)//插入排序
 46     {
 47         if(multi && exist(node.b) != -1)
 48             return;
 49         int i;
 50         for(i = counter++; i >= 0; --i)
 51             if(node.b < array[i].b)
 52                 array[i+1] = array[i];
 53             else
 54             {
 55                 array[i+1]=node;
 56                 break;
 57             }
 58     }
 59     device_node* begin()
 60     {
 61         return &array[1];
 62     }
 63     device_node* end()
 64     {
 65         return &array[counter + 1];
 66     }
 67     int exist(int b)//某个带宽是否已经插入了
 68     {
 69         int begin = 1, end = counter + 1;
 70         int mid;
 71         while(begin != end)
 72         {
 73             mid = (begin+end)/2;
 74             if(array[mid].b > b)
 75                 end = mid;
 76             else if(array[mid].b < b)
 77                 begin = mid + 1;
 78             else
 79                 break;
 80         }
 81         if(begin == end)
 82             return -1;
 83         else
 84             return array[mid].p;
 85     }
 86     int min_p(int b)//找满足条件的最便宜设备
 87     {
 88         int i;
 89         int min = 200000000;
 90         for(i = 1; i <= counter; ++i)
 91             if(array[i].b >= b && array[i].p && array[i].p < min)
 92                 min = array[i].p;
 93         return (min == 200000000)? -1 : min;
 94     }
 95     void print()
 96     {
 97         int i;
 98         for(i = 1; i <= counter; ++i)
 99             printf("(%d, %d) ", array[i].b, array[i].p);
100         printf("\n");
101     }
102 };
103 
104 int main()
105 {
106     int t, n;
107     scanf("%d", &t);
108     devices system[100];
109     devices f(10000);
110     while(t--)
111     {
112         scanf("%d", &n);
113         int i, j;
114         int m, b, p;
115         f.init();
116         for(i = 0; i < n; ++i)
117         {
118             system[i].init();
119             scanf("%d", &m);
120             for(j = 0; j < m; ++j)
121             {
122                 scanf("%d %d", &b, &p);
123                 device_node tmp1(b, p);
124                 system[i].append(tmp1, false);
125                 device_node tmp2(b, 0);
126                 if(i == 0)
127                     f.append(tmp1, true);
128                 else
129                     f.append(tmp2, true);
130             }
131         }
132         for(i = 0; i < n; ++i)
133             system[i].print();
134         //int pass;
135         //for(pass = 10; pass <= 200; pass += 10)
136         //if(f.exist(pass))
137         // printf("%d pass\n", pass);
138         // else
139         // printf("%d not pass\n", pass);
140         f.print();
141         device_node *iter;
142         for(i = 1; i < n; ++i)
143         {
144             for(iter = f.begin(); iter != f.end(); ++iter)
145             {
146                 int exist_p = system[i].exist(iter->b);
147                 int system_min_p = system[i].min_p(iter->b);
148                 int f_min_p = f.min_p(iter->b);
149                 if(iter->p)// 如果已经初始化了(或者说这个全局带宽已经出现过了)
150                 {
151                     if(system_min_p == -1)//如果没有更大的带宽,那么是这种选法是不可能的
152                         iter->p = 0;
153                     else
154                         iter->p += system_min_p;
155                 }
156                 if(exist_p != -1 && f_min_p != -1)//有一样的带宽出现了
157                 {
158                     if(iter->p == 0)
159                         iter->p = exist_p + f_min_p;
160                     else
161                         iter->p = iter->p < exist_p + f_min_p? iter->p : exist_p + f_min_p;
162                 }
163             }
164             f.print();
165         }
166         double result = 0;
167         for(iter = f.begin(); iter != f.end(); ++iter)
168         {
169             if(iter->p)
170             {
171                 double shang = double(iter->b)/double(iter->p);
172                 result = result > shang? result : shang;
173             }
174         }
175         printf("%.3f\n", result);
176     }
177 }
178         
179    

 

 

 

posted on 2012-10-30 16:04  zhengchl  阅读(221)  评论(0编辑  收藏  举报

导航