POJ-1018(DP)
1018: Communication System
时间限制:
1000ms
内存限制:
65536kB
描述
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.
输入
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(1到32767) in the same line, each indicating the bandwidth and the price of the device respectively, corresponding to a manufacturer.
输出
Your program should produce a single line for each test case containing a single number which isthe maximum possible B/P for the test case. Round the numbers in the output to 3 digits after decimal point.
样例输入
1 3
3 100 25 150 35 80 25
2 120 80 155 40
2 100 100 120 110
样例输出
0.649
这题不会的,看了下解题报告,了解了一下解题思路.
(1)题目意思大概就是有n个devices,每个都需要一个bandwidth,而这个会有很多商家提供,价格不同,现在在n个中,每个选一个,但是着n个中选B最小的,而所有选的price和最小,即是B/p最大。-
(2)题目讲在不同设备中个取出一种设备,使得这些设备带宽的最小值和它们价值的总和的比最大.
贪心思路:
1,获得一个最小和最大带宽:最小带宽是各个设备最小带宽的最小值,最大带宽是各个设备最大带宽的最小值.
2,从最小值递增到最大值进行寻找,计算各种设备价钱的最小值的和,然后计算出一个比值,如果比值比当前比值大,更换当前比值;
3,重复2直到结束.
#include<stdio.h>
#include<string.h>
int main()
{
int i,j,k,m,min,max,high,low,t,sum;
int b[101][101],p[101][101],num[101],flag[32767];
double b_p,mmax;
scanf("%d",&t);
while(t--)
{
memset(flag,0,sizeof(flag));//初始flag为0,用来标记带宽值
high=32767;
low=32767; //正整数的可能最大值
scanf("%d",&m);
for(i=0;i<m;i++)
{
min=10000;//正整数的可能最大值,取决于测试数据是否变态, int型最大是32767, 一般要尽量开大一点
max=1;//正整数的可能最小值
scanf("%d",&num[i]);//num[i]为各个设备的备用厂商数目
for(j=0;j<num[i];j++)
{
scanf("%d",&b[i][j]);
scanf("%d",&p[i][j]);
flag[b[i][j]]=1;//当前贷款带宽标记为1
if(max<b[i][j])//当前设备最大值
max=b[i][j];
if(min>b[i][j])//当前设备最小值
min=b[i][j];
}
if(low>min)//各个设备最小带宽中的最小值
low=min;
if(high>max)//各个设备最大带宽中的最小值
high=max;
}
mmax=0;//最终结果
for(i=low;i<=high;i++)//结合下面的if(flag[i])则无须次次都是利用循环来获得i值,节省了大量时间
{
if(flag[i])//找出经标记过的带宽值(动态规划说白了就是以空间换取时间)
{
sum=0;
for(j=0;j<m;j++)
{
min=32767;
for(k=0;k<num[j];k++)
{
if(i <=b[j][k])
{
if(min>p[j][k])//获得当前设备所有供应商中最低的价格
min=p[j][k];
}
}
sum+=min;
}
b_p=(double)i/(double)sum;
if(mmax<b_p)
mmax=b_p;
}
}
printf("%.3lf\n",mmax);
}
return 0;
}