poj 1018 Communication System 动态规划

来源:互联网 发布:mocha跟踪数据导入ae 编辑:程序博客网 时间:2024/06/05 23:51
Communication System
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 25393 Accepted: 9054

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 33 100 25 150 35 80 252 120 80 155 402 100 100 120 110

Sample Output

0.649

Source

Tehran 2002, First Iran Nationwide Internet Programming Contest

解题报告:
题意:
先输入测试组数T,之后每组先输入一个n,代表n种产品,
之后n行,每行先输入一个数mi,代表第i种产品有mi种型号。之后输入mi对int,代表mi个不同型号 产品的参数 ,每对第一个是bandwidth,第二个是price。
现在要求在每种产品中选一个型号。
最终使下列公式的结果最大
(所选中n个型号中最小bandwidth值)/(所选中n个型号的price之和)

n最大100,mi最大100。
可以说暴力完全无解。

如果确定一个较好的顺序进行计算,那么可以对每个元素只处理一遍。

我思考了半天,怎么做,最后想出来了  感觉上还是比较爽的。
首先这个式子,很复杂。
关键是找到一个恰到好处的顺序。
我就是看到了那个min(∑ban),怎样一个顺序能使它,对每个元素仅遍历一遍,也就是说能在近乎O(1)的时间算出选择变化时min(∑ban)的变化呢?
答案就是做一定的处理 使按照 min(∑ban) 逐渐减小 的顺序 计算。

将上去RE,后AC,现总结一下:
1.
数组越界
1)数组开小
我以前出现过的RE错误,图论中和2*maxn大小的数组,常常开成 maxn,该题的maxn*maxn大小数组开成了maxn大小
2)访问出界
单调队列时,队列空了还在弹出或删除元素。
2.
分母为0,
这个绝对不可忽视。



#include<cstdio>#include<string>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>#include<climits>#include<queue>#include<vector>#include<map>#include<sstream>#include<set>#include<stack>#include<cctype>#include<utility>#pragma comment(linker, "/STACK:102400000,102400000")#define PI 3.1415926535897932384626#define eps 1e-10#define sqr(x) ((x)*(x))#define FOR0(i,n)  for(int i=0 ;i<(n) ;i++)#define FOR1(i,n)  for(int i=1 ;i<=(n) ;i++)#define FORD(i,n)  for(int i=(n) ;i>=0 ;i--)#define  lson   num<<1,le,mid#define rson    num<<1|1,mid+1,ri#define MID   int mid=(le+ri)>>1#define zero(x)((x>0? x:-x)<1e-15)#define mk    make_pair#define _f     first#define _s     secondusing namespace std;//const int INF=    ;typedef long long ll;//const ll inf =1000000000000000;//1e15;//ifstream fin("input.txt");//ofstream fout("output.txt");//fin.close();//fout.close();//freopen("a.in","r",stdin);//freopen("a.out","w",stdout);const int INF =0x3f3f3f3f;const int maxn=  110  ;//const int maxm=    ;int num[maxn];int st[maxn];int delegate[maxn];int n,cnt;int mini;struct DEV{    int b,p;}dev[maxn][maxn];bool cmp(DEV x,DEV y){    return x.b>y.b;}double ans,tot;void first_round(){     tot=0;    for(int i=1;i<=n;i++)    {        st[i]=num[i]+1;        delegate[i]=dev[i][1].p;        for(int j=1;j<=num[i];j++)        {            if(dev[i][j].b<mini)  {  st[i]=j ;break;}//              tmp=min(tmp,dev[i][j]);            if(dev[i][j].p<delegate[i])  delegate[i]=dev[i][j].p;        }        tot+=delegate[i];    }//    cout<<ans<<endl;//    cout<<"mini "<<mini<<" tot "<<tot<<endl;    ans=max(ans,  mini/tot);}struct Node{    int b,p,row;    Node(){}    Node(int b,int p,int row):b(b),p(p),row(row){}    bool operator<(const Node &y)const    {        return b>y.b;    }} a[maxn*maxn];//数组开成maxn*maxn就错了!!!void intergrade(){    cnt=0;    for(int i=1;i<=n;i++)    {        for(int j=st[i];j<=num[i];j++)//这里<=num[i]是个容易写错的地方        {            a[++cnt]=Node(dev[i][j].b,dev[i][j].p,i);        }    }    sort(a+1,a+1+cnt);}void second_round(){   for(int i=1;i<=cnt;i++)   {       int row=a[i].row;       mini=min(a[i].b,mini);       tot-=delegate[row];       tot+=a[i].p;       delegate[row]=a[i].p;       ans=max(ans, mini/tot);   }}int main(){    int T;scanf("%d",&T);    while(T--)    {        scanf("%d",&n);        mini=INT_MAX;ans=-INT_MAX;        for(int i=1;i<=n;i++)        {            scanf("%d",&num[i]);            for(int j=1;j<=num[i];j++)            {                scanf("%d%d",&dev[i][j].b,&dev[i][j].p);            }            sort(dev[i]+1,dev[i]+1+num[i],cmp);            mini=min(mini,dev[i][1].b);        }        first_round();        intergrade();        second_round();        printf("%.3lf\n",ans);    }    return 0;}


0 0