题意:在输入的公司里面,每个公司都要选择一条宽带线,但是能够使用的线的带宽是最“窄”的那根,
每根带宽线都有一个band和一个price;
题目的要求是输出带宽/总价值的最大比值。
例如:
题目中的列子:
1 3 3 100 25 150 35 80 25 2 120 80 155 40 2 100 100 120 110
0.649
第一排的第一个数为测试的个数,第二个数为公司的总数(貌似换行写也没什么的)。
接下来的为各个公司的情况,首先输入这个公司有几种线,然后输入每条线的band和price。
输出的结果的解释:120/(110+40+35) = 0.649 既为第一个公司选择了 150 35,第二个公司选择了155 40
第三个公司选择了120 110.
解题思路:这道题目用贪心的思路来解决是最好的 比较容易理解,因为每一个公司都要选择线,
所以每个公司的band最小的最大值为总band的最小值,每个公司的band最大值的最小值为总能够被选取的band的最小值。
所以总选的band就在这个范围之间。
但是 由于自己是在学习dp 所以这道题目是用的dp的思路。
思路来源:discuss,
代码:
#include <iostream>
using namespace std;
int dp[101][10010];
//dp【i】【j】表示前i个物品最小带宽为j时的最小总和(不表示每一家电器都选了的判断)
struct node
{
int band;
int price;
};
int mins(int a,int b)
{
if(a<b)
return a;
else
return b;
}
void work()
{
node a[101][101];
int i,j,k;
int n;
int geshu[101];
int p = 1 ;
int max = 0;
int min = 99999;
scanf("%d",&n);
for(i = 1 ; i <= n ; i ++)
{
scanf("%d",&geshu[p]);
for(j = 1 ; j <= geshu[p] ; j++)
{
scanf("%d%d",&a[i][j].band,&a[i][j].price);
if(a[i][j].band > max)
max = a[i][j].band;//找出带宽的最大值
if(a[i][j].band < min)
min = a[i][j].band;//貌似加入了 寻找带宽的最大值和最小值结果用的时间多了。
}
p++;
}
for(i = 1 ; i <= n ; i++)
for(j = 1 ; j <= max; j++)
dp[i][j] = 12000; //dp数组的初始值
for(i = 1 ; i <=geshu[1]; i++)
{
if(dp[1][a[1][i].band] > a[1][i].price) //没有直接赋值的原因是可能会出现重复的带宽
dp[1][a[1][i].band] = a[1][i].price ;
// cout<<dp[1][a[1][i].band]<<" "<<a[1][i].band<<endl;
}//只有第一个公司时每个带宽下的最小的price
for(i = 2 ; i <= n ; i++ )
for(j = min -1 ; j <= max ; j++)//min-1貌似是多的 但是为了不出错多算一次也没什么的 囧
{
if(dp[i-1][j] != 12000)
{
// cout<<dp[i-1][j]<<"!!!! "<<j<<endl;
for(k = 1 ; k <= geshu[i] ; k++)
{
int min = j;
if(a[i][k].band < min)
{
min = a[i][k].band;
}dp[i][min] = mins(dp[i][min],(dp[i-1][j]+a[i][k].price));//好好的体会下这句话
//如果出现了在当前j的情况下有a[i][k].band 就没有计算dp[i][j]
//去计算了dp[i][min]的时候继承了在dp[i-1][j]获得的结果下进行动态规划的
// cout<<dp[i][min]<<"! "<<min<<endl;
}
}
}
double temp;
double result = 0;
/* for(i = 1 ; i <= n ; i++ )
for(j = 1 ; j <=max ; j++)
{
if(dp[i][j] != 12000)
cout<<dp[i][j]<<" "<<j<<endl;
}*/
for(j = min -1 ; j <= max ; j++)//计算比值并找出最大的比值
{
if(dp[n][j] != 12000)
{
// cout<<j<<" "<<dp[n][j]<<endl;
temp = (double)j/(double)dp[n][j];
// cout<<temp<<endl;
if(temp > result)
result = temp;
}
}
printf("%.3f/n",result);
}
int main()
{
int n;
scanf("%d",&n);
while(n--)
{
work();
}
return 0;
}