解題報告:
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