poj 1018

题意:

某公司要建立一套通信系统,该通信系统需要n种设备,而每种设备分别可以有m1、m2、m3、...、mn个厂家提供生产,而每个厂家生产的同种设备都会存在两个方面的差别:带宽bandwidths 和 价格prices。

现在每种设备都各需要1个,考虑到性价比问题,要求所挑选出来的n件设备,要使得B/P最大。

其中B为这n件设备的带宽的最小值,P为这n件设备的总价。


分析:此题目可用多种方法求解,DP 、 搜索 、贪心 、三分法 


这里讲dp的思路。


我们定义状态dp 【i】【j】 表示选择了前 i 个宽带其容量为 j 的最小费用。 

很容易得到转移方程 :dp【i】【j】=min(dp【i】【j】,dp【i-1】【k】+p);

注意选择 j 的时候的大小情况。


顺便提供一下贪心的思路。(正确性未知)

从初始的第一个要选的宽带的每一个开始,每次向下贪心选择一个总的 B/P 的最大值,找出其中最大的既为答案。有兴趣的可以验证一下正确性!


dp代码:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. #include <cstdio>  
  2. #include <cstring>  
  3. #include <algorithm>  
  4. using namespace std;  
  5. const int inf = 0x3f3f3f3f;  
  6. int dp[120][1200];  
  7.   
  8. int main()  
  9. {  
  10.     int T;  
  11.     scanf("%d",&T);  
  12.     while(T--)  
  13.     {  
  14.         int n;  
  15.         scanf("%d",&n);  
  16.         for(int i=1; i<=n; i++)  //初始化  
  17.         {  
  18.             for(int j=0; j<1100; j++)  
  19.                 dp[i][j]=inf;  
  20.         }  
  21.         for(int i=1; i<=n; i++)   //dp  
  22.         {  
  23.             int num;  
  24.             scanf("%d",&num);  
  25.             for(int j=1; j<=num; j++)  
  26.             {  
  27.                 int p,b;  
  28.                 scanf("%d%d",&b,&p);  
  29.                 if(i==1)  
  30.                 {  
  31.                     dp[1][b]=min(dp[1][b],p);  
  32.                 }  
  33.                 else  
  34.                 {  
  35.                     for(int k=0; k<1100; k++)  
  36.                     {  
  37.                         if(dp[i-1][k]!=inf)  
  38.                         {  
  39.                             if(k<=b)  
  40.                                 dp[i][k]=min(dp[i][k],dp[i-1][k]+p);  
  41.                             else  
  42.                                 dp[i][b]=min(dp[i][b],dp[i-1][k]+p);  
  43.                         }  
  44.                     }  
  45.                 }  
  46.             }  
  47.         }  
  48.         double ans=0;  
  49.         for(int i=0; i<1100; i++)  
  50.         {  
  51.             if(dp[n][i]!=inf)  
  52.             {  
  53.                 double k=(double)i/dp[n][i];  
  54.                 if(k>ans)  
  55.                     ans=k;  
  56.             }  
  57.         }  
  58.         printf("%.3lf\n",ans);  
  59.     }  
  60.     return 0;  
  61. }  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值