题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1069
题目大意:


	题意分析:
	  题目本身描述得比较绕口,这里利用题目给的测试用例的输入描述一下:
	              生产的   厂家m1     厂家m2    厂家m3
	              厂家数   B1   P1    B2  P2    B3 P3
	  路由设备n1:  3     [100 25]   [150 35]  [80 25]
	  路由设备n2:  2     [120 80]   [155 40]
	  路由设备n3:  2     [100 100]  [120 110]
	  
	  简单而言,有n种通讯设备(在本题中可类比成网络路由器),
	  每种路由器最少有1个厂家、最多可以有m个厂家负责生产,
	  当然,不同的厂家生产的路由器性价比都是不一样的,
	  而影响路由器性价比的取决于其 带宽B 和 价格P
	  现在某通讯公司要采购n个路由器集成为一个网络系统,
	  每个路由器可以从不同的厂家中采购。
	  由于带宽存在短板效应,这个网络系统的最大带宽 sysB 取决于这n个路由中最小的带宽
	  
	  而这个网络系统的价格 sysP 等于这n个路由的价格之和
	  问以最好的性价比为目标去选购n个路由组装网络系统,
	  这个性价比的值 sysB/sysP 是多少 ?
	  
	解题思路:
	  首先需要简化状态。
	    题目要求的最终状态性价比是由 带宽和价格 两个变量影响的,不易构造DP的状态转移方程。
		为此可将问题状态转化为以下问题集:
		【求在[各种带宽]的情况下组装网络系统的[最小价格]】
		
令 dp[e][B] 表示选择[前e个]路由设备所构成带宽为B的系统所需支付的最小价格,
	 注意B是离散的,且因为短板效应受[前e-1]路由设备构成的带宽影响
	 那么状态转移方程为:
	   for(int i=1;i<=n;i++)
       {
           for(int j=1;j<=m[i];j++)
           {
               int B=b[i][j];//设备i被厂家j生产时的带宽B
               int P=p[i][j];//设备i被厂家j生产时的价格P
               if(i==1)
               {
                   dp[1][B]=min(dp[1][B], P);
               }
               else
               {
                   for(int k=1;k<B;k++)//最小带宽发生改变
                   {
                       if(dp[i-1][k]<inf)//前状态存在
                       {
                           dp[i][k]=min(dp[i][k], dp[i-1][k]+P);
                       }
                   }
                   for(int k=B;k<500;k++)//最小带宽不发生改变
                   {
                       if(dp[i-1][k]<inf)//前状态存在
                       {
                           dp[i][B]=min(dp[i][B], dp[i-1][k]+P);
                       }
                   }
               }
           }
       }


思考:暑假也做过dp记录状态的题,还是没有搞的太明白
全部代码:

#include <iostream>
#include <stdio.h>

using namespace std;
#define LL long long
#define p1 first
#define p2 second
//memset(a, 0, sizeof(a));
//stack堆栈 queue队列 priority_queue优先队列
//vector向量 multiset平衡二叉树 deque双端队列
//pair{T1 first;T2 second;} greater<T>
//unordered_map 哈希map
const int inf=(1<<31)-1;
int b[105][105]={0};//设备i被厂家j生产时的带宽B
int p[105][105]={0};//设备i被厂家j生产时的价格P
int m[105];
int dp[105][500];   //表示选择[前i个]路由设备所构成带宽为j的系统所需支付的最小价格,

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&m[i]);
            for(int j=1;j<=m[i];j++)
            {
                scanf("%d%d",&b[i][j], &p[i][j]);
            }
        }

        for(int i=1;i<105;i++)
        {
            for(int j=0;j<500;j++)
            {
                dp[i][j]=inf;
            }
        }

        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m[i];j++)
            {
                int B=b[i][j];
                int P=p[i][j];
                if(i==1)
                {
                    dp[1][B]=min(dp[1][B], P);
                }
                else
                {
                    for(int k=1;k<B;k++)
                    {
                        if(dp[i-1][k]<inf)
                        {
                            dp[i][k]=min(dp[i][k], dp[i-1][k]+P);
                        }
                    }
                    for(int k=B;k<500;k++)
                    {
                        if(dp[i-1][k]<inf)
                        {
                            dp[i][B]=min(dp[i][B], dp[i-1][k]+P);
                        }
                    }
                }
            }
        }
        double MAX=0;
        for(int i=1;i<500;i++)
        {
            if(dp[n][i]<inf)
            {
                MAX=max(MAX, 1.0*i/dp[n][i]);
            }
        }
        printf("%.3f\n",MAX);

    }

    return 0;
}