解题报告:
1)方式一(对应maxbp)
分为两个集合S和S1:
1:初始情况下S[ (65535, 0) ], S1 [ ]为空
输入第一批数据后:(100 25)( 150 35)( 80 25)
S1为[(100 25)( 150 35)( 80 25)],然后删除S1中不可能为最优解的二值对,即(80 25)得新的S1为[(100 25)( 150 35)]
令S = S1, S1 为空
2:输入第二批数据(120 80)( 155 40)
S1为[(100 105)( 100 65)( 120 115) ( 150 75)]删去S1中不可能的最优解二值对,即(100 105)和( 120 115)得到新的S1为[( 100 65) ( 150 75)]
令S = S1, S1 为空
3:输入第三批数据(100 100 )(120 110)
得S1为[(100 165)(100 175)(100 175)(120 185)]删去S1中不可能的最优解二值对,即(100 175)得到新的S1为[( 100 165) ( 120 185)]
令S = S1, S1 为空
4:求最大值,即100/165 与 120/185谁更大??
这一解题思路可以求得最大值,但是一直不能AC,总是超时!!2)方式二(对应maxbp2)
参考的是网上的方案,进行枚举
本题中带宽是选取所有设备中的最小值,而价格是选取所有设备的价格总和。如果某个制造商生产的某种设备,它的带宽较高而价格较低,那么选取它的可能性就比较大。再进一步说,如果所选取的n种设备的带宽的最小值b已经确定,那么对于某种设备,我们就可以在那些生产这种设备的,带宽大于等于b的制造商中进行选择。当然是选那个价格最低的设备,因为答案的分子已经确定为b,所以分母越小越好。看来只要枚举b,再对于每个设备贪心的选择最小价格就可以了,时间复杂度为O(mnB),B为带宽枚举的数量。但问题又来了,应该怎么枚举带宽,题目中并未给出带宽的取值范围,如果从0..maxB一个一个枚举的话,既费时又会造成过多重复情况(如果枚举那些在输入中出现的两个连续带宽之间的值,最后的答案是一样的)。所以我们应该采取某个方法记录输入中出现过的带宽(STL中的set是个不错的选择),再枚举这些带宽。
顺利AC,这个方法很直接,一次就AC了,数据结构也比较简单。确实比我想的第一种解决方案来的简单。
#include <iostream>
#include <cstdio>
#include <vector>
#include <set>
#include <limits>
#include <algorithm>
#include <list>
#include <iomanip>
using namespace std;
bool mycomp(pair<int,int> p1, pair<int,int> p2)
{
if(p1.first < p2.first)
return true;
if(p1.first > p2.first)
return false;
if(p1.second < p2.second)
return false;
if(p2.second > p2.second)
return true;
return false;//相等必须返回true
}
typedef vector<int>& VIR;
double maxbp(VIR bwidth,VIR price,VIR fnumbers)
{
double max = 0;
list<pair<int,int> > s;//price,bandwidth
list<pair<int,int> > s1;//price,bandwidth
list<pair<int,int> >::iterator prev,next,pos;
s.push_back(make_pair<int,int>(0,numeric_limits<int>::max()));
int beg = 0,end = 0;
for(int i = 0; i < fnumbers.size(); ++i)
{
end += fnumbers[i];
for(int j = beg; j < end; ++j)
{
//for(int k = 0; k < sb.size(); ++k)
for(pos = s.begin(); pos != s.end(); ++pos)
{
int b = min(pos->second, bwidth[j]);
int p = pos->first + price[j];
s1.push_back(make_pair<int,int>(p,b));
}
}
s1.sort(mycomp);
prev = next = s1.begin();
for(++next; next != s1.end(); )
{
if(next->second <= prev->second)
next = s1.erase(next);
else
{
prev = next;
++next;
}
}
s.swap(s1);
s1.clear();
beg = end;
}
for(pos = s.begin(); pos != s.end(); ++pos)
{
if(pos->second*1.0/pos->first > max)
max = pos->second*1.0/pos->first;
}
return max;
}
typedef vector<int>& VIR;
double maxbp2(VIR bwidth,VIR price,VIR fnumbers,set<int>& ewidth)
{
double max = 0;
int B,P;
bool bval;
for(set<int>::iterator pos = ewidth.begin(); pos != ewidth.end(); ++pos)
{
B = *pos;
P = 0;
int beg = 0,end = 0;
for(int i = 0; i < fnumbers.size(); ++i)
{
int minp = numeric_limits<int>::max();
end += fnumbers[i];
bval = false;
for(int j = beg; j < end; ++j)
{
if(bwidth[j] >= B && price[j] < minp)
{
minp = price[j];
bval = true;
}
}
if(bval == false)goto End;
P += minp;
beg = end;
}
if(B*1.0/P > max)
max = B*1.0/P;
End:;}
return max;
}
int main()
{
freopen("in.txt","r",stdin);
vector<int> bwidth,price,fnumbers;
set<int> ewidth;//用于枚举
int ib,ip;
int t;
cin>>t;// 1 <= t <= 10
while(t--)
{
bwidth.clear();
price.clear();
fnumbers.clear();
int n;
cin>>n;//1 ≤ n ≤ 100
while(n--)
{
int mi;//1 ≤ mi ≤ 100
cin>>mi;
fnumbers.push_back(mi);
while(mi--)
{
cin>>ib>>ip;
bwidth.push_back(ib);
ewidth.insert(ib);
price.push_back(ip);
}
}
//cout<<fixed<<setprecision(3)<<maxbp(bwidth,price,fnumbers)<<endl;
cout<<fixed<<setprecision(3)<<maxbp2(bwidth,price,fnumbers,ewidth)<<endl;
}
}
测试数据:
1 3 3 100 25 150 35 80 25
2 120 80 155 40
2 100 100 120 110