POJ 1018 Communication System dp

Communication System
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 23065   Accepted: 8197

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


题目大意:

有n个设备,每个设备有m个选择,每个选择具有两种不同属性,一个是带宽b,一个是价格p。

求选好n种设备,使得所选设备中最小的b除以“p的总和”的值最大


下面是自己的ac代码

里面都有注释说明了

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <memory>
#include <string>
#include <vector>
#include <list>
#include <map>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <numeric>
#include <functional>
#define maxn 1000005
#define mod 100007

using namespace std;
typedef unsigned long long ll;
int b[105][105],p[105][105];
int num[105];
int dp[105][105*105];
//dpij,i表示当前遍历到了第i个商品,j表示所能选择的最小带宽
//dp值为当前已选择的所有商品价格除以最小的厂商带宽
//在dp到i时,对于i-1时的每一个状态(j取不同的值),
//都用其(dp[i-1][j])遍历一遍第i个商品的所有厂商,
//并且求出每一个j对应的最小 “总和p”



int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        vector<int> g[105];
        //vector用于减少运行时间,因为第二个下标会有很大冗余
        //很多值不必遍历,可以将i-1时出现的j值记录下来,
        //到i后直接使用
        memset(b,0,sizeof(b));
        memset(p,0,sizeof(p));
        memset(dp,-1,sizeof(dp));
        memset(num,0,sizeof(num));
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;i+=1){
            scanf("%d",&num[i]);
            for(int j=0;j<num[i];j+=1){
                scanf("%d %d",&b[i][j],&p[i][j]);    //第i个商品第j个厂商的信息
                if(i==0){
                    dp[0][b[i][j]]=p[i][j];
                    g[0].push_back(b[i][j]);       //为了减小时间,可以用一个vector来记录存在的
                }
            }
        }

        float ans=0.0;
        for(int i=1;i<n;i+=1){
            int sz=g[i-1].size();
            for(int j=0;j<sz;j+=1){
                for(int k=0;k<num[i];k+=1){
                    int minb=min(g[i-1][j],b[i][k]);
                    if(dp[i][minb]==-1){
                        //如果等于-1证明这个值时第一次更新到,因为是求最小值,
                        //所以这时不可以直接使用min来对比,直接赋值即可
                        dp[i][minb]=dp[i-1][g[i-1][j]]+p[i][k];
                        g[i].push_back(minb);
                    }
                    else{
                        //如果不等于-1,证明这个最小带宽值对应的dp值已经更新过
                        //那么需要找出最小的“总和p”
                        dp[i][minb]=min(dp[i][minb],dp[i-1][g[i-1][j]]+p[i][k]);
                    }
                }
            }

            if(i==n-1){
                for(int j=0;j<g[i].size();j+=1){
                    ans=max(ans,(float)g[i][j]/(float)dp[i][g[i][j]]);
                }
            }
        }

        if(n==1){
            for(int i=0;i<g[0].size();i+=1){
                ans=max(ans,(float)g[0][i]/(float)dp[0][g[0][i]]);
            }
        }
        printf("%.3f\n",ans);
    }

    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章