poj 1018 Communication System

7 篇文章 0 订阅

Description

We have received an order from Pizoor Communications Inc. for a special communication system. The system consists of several devices. For each device, we are free to choose from several manufacturers. Same devices from two manufacturers differ in their maximum bandwidths and prices.
By overall bandwidth (B) we mean the minimum of the bandwidths of the chosen devices in the communication system and the total price (P) is the sum of the prices of all chosen devices. Our goal is to choose a manufacturer for each device to maximize B/P.

Input

The first line of the input file contains a single integer t (1 ≤ t ≤ 10), the number of test cases, followed by the input data for each test case. Each test case starts with a line containing a single integer n (1 ≤ n ≤ 100), the number of devices in the communication system, followed by n lines in the following format: the i-th line (1 ≤ i ≤ n) starts with mi (1 ≤ mi ≤ 100), the number of manufacturers for the i-th device, followed by mi pairs of positive integers in the same line, each indicating the bandwidth and the price of the device respectively, corresponding to a manufacturer.

Output

Your program should produce a single line for each test case containing a single number which is the maximum possible B/P for the test case. Round the numbers in the output to 3 digits after decimal point.

Sample Input

1 3
3 100 25 150 35 80 25
2 120 80 155 40
2 100 100 120 110

Sample Output

0.649

思路:

方法一:看见很多人用dp

     令 n:设备数 
        m:厂家数 
        B(e, f) 表示 设备e被厂家f生产时的带宽B 
        P(e, f) 表示 设备e被厂家f生产时的价格P 
        其中 e∈[1,n]. f∈[1,m] 
 
     令 dp(e, B) 表示选择[前e个]路由设备所构成带宽为B的系统所需支付的最小价格, 
     注意B是离散的,且因为短板效应受[前e-1个]路由设备构成的带宽影响 
 
     那么状态转移方程为: 
        ① 当 e = 1 时: 
            for(f = 1 : m) { 
                b = B(e, f); 
                p = P(e, f); 
                dp(e, b) = min{ dp(e, b), p };  #相当于选每个B对应的min价格,只有一个设备
            } 
        ② 当 e > 1 时: 
            for(e = 2 : n) { 
                for(f = 1 : m) { 
                    for(bandwidth : 前e-1次决策中有效的系统带宽) { 
                        b = min{ B(e, f), bandwidth };      // 短板效应 
                        dp(e, b) = min{ dp(e, b), dp(e - 1, bandwidth) + P(e, f) }; 
                    } 
                } 
            } 

方法二:(看的别人的,觉得挺好的,实现起来简单)

1,获得一个最小和最大带宽:最小带宽是各个设备最小带宽的最大值,最大带宽是各个设备最大带宽的最小值.
2,从最小值递增到最大值进行寻找,计算各种设备价钱的最小值的和,然后计算出一个比值,如果比值比当前比值大,更换当前比值;
3,重复2直到结束.

方法三:(自己想的,有很多可以改进的地方,感觉)

1.对于每一个设备,首先按照B排序,快排即可,对于每一个设备,搜索最小的P,记录在current_min中,Price = sum(current_min)。

2.给每一个设备 指定一个指针,current_index[i],从所有的指针中选取B最小的,设最小B所在的设备号为min_index,最小带宽为minB;

3.则该种情况对应的B/P = minB/Price;

4.这个时候要判断是否应该更新Price,如果P[min_index][current_index[min_index]] == current_min[min_index],寻找P[min_index][current_index[min_index]+1 ~ end]的最小值,更新current_min[min_index]和Price,通俗点说就是该设备对应的最小价格所在的带宽太小。

5.重复2~4,直到某种设备遍历到了最后一个供销商

曾经考虑过每次不选择minB,而是直接遍历没有设备,不知道怎么样。

#include<iostream>
#include<memory.h>
#include<stdio.h>
using namespace std;
//快速排序
int partition(int B[],int P[],int p,int r){
    int baseB = B[p];
    int baseP = P[p];
    while(p < r){
        while(p < r && B[r] >= baseB)
            r--;
        if(p <r){
            B[p] = B[r];
            P[p] = P[r];
            p++;
        }
        while(p <r && B[p] <= baseB){
            p++;
        }
        if(p < r){
            B[r] = B[p];
            P[r] = P[p];
            r--;
        }
    }
    B[p] = baseB;
    P[p] = baseP;
    return p;
}
void quickSort(int B[],int P[],int p,int r){
    if(p < r){
        int q = partition(B,P,p,r);
        quickSort(B,P,p,q-1);
        quickSort(B,P,q+1,r);
    }
}

int main(){
    int total_case;
    cin>>total_case;
    int total;
    int B[110][110];
    int P[110][110];
    int length_source[110];
    for(int _ = 0; _ < total_case; _++){
        //获取输入
        double result = 0;
        cin>>total;
        int sum = 0;
        for(int i = 0; i < total;i++){
            cin>>length_source[i];
            sum += length_source[i];
            for(int j = 0; j < length_source[i]; j++){
                cin>>B[i][j];
                cin>>P[i][j];
            }
            quickSort(B[i],P[i],0,length_source[i]-1);
        }
        //开始搜查
        //从每行中选出带宽最小的作为最小带宽,查找其后的元素 在这里可以记录一下每行的max
        int current_index[110];
        int current_min[110];//记录每行当前的最小值
        int result_index[110];
        memset(current_index,0,sizeof(current_index));
        memset(current_min,-1,sizeof(current_min));
        int flag = 1;
        int tempResult = 0;
        for(int i = 0; i <total;i++){
            int minPrice = P[i][current_index[i]];
            for(int j = current_index[i]+1; j < length_source[i]; j++){
                if(minPrice > P[i][j]){
                    minPrice = P[i][j];
                }
            }
            current_min[i] = minPrice;
            tempResult += current_min[i];
        }
        //最后还需要迭代一次每个只剩最后一个元素的情况
        while(flag){
            //选取最小值
            int i = 0;
            int mint = B[i][current_index[i]];
            int minIndex = i;
            for(i++; i < total;i++){
                if(B[i][current_index[i]] < mint){
                    mint = B[i][current_index[i]];
                    minIndex = i;
                }
            }
            if(current_index[minIndex] == length_source[minIndex]-1)
                flag = 0;
            double temp = mint*1.0/tempResult;
            if(temp > result){
                result = temp;
                for(i = 0;i  <total; i++)
                    result_index[i] = current_index[i];
            }
            //更新最小值
            if(P[minIndex][current_index[minIndex]] == current_min[minIndex]){
                tempResult -= current_min[minIndex];
                int minValue = P[minIndex][current_index[minIndex]+1];
                for(int j = current_index[minIndex]+2; j < length_source[minIndex]; j++){
                    if(P[minIndex][j] < minValue){
                        minValue = P[minIndex][j];
                    }
                }
                current_min[minIndex] = minValue;
                tempResult += minValue;
            }
            //更新当前坐标
            current_index[minIndex]++;

        }
        printf("%.3f\n",result);
    }
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值