PKU-1018:Communication System
keyword
BruteForce C++
問題概要
N(<100)個のデバイスがある。それぞれのデバイスはM(<100)個の中からオプションを一つ選ぶ。各オプションはバンド幅bとコストpを持つ。バンド幅の最小値Bとコストの総和Pに対してB/Pを最大化する問題。
解法
Bについて全探索する。データ構造を工夫してBを決めたらB/Pの最大値をO(N * log M)で計算できる様にする。全体の計算量はO(N^2*M*log M)。
#include <cstdio> #include <set> #include <algorithm> #include <vector> #include <map> using namespace std; vector<int> bs[110], ps[110]; map<int,int> dict[110]; int N; double check(int limit){ int total=0; for(int i=0; i<N; i++){ total += dict[i].lower_bound(limit)->second; } return (double)limit/total; } double solve(){ for(int i=0; i<N; i++){ dict[i].clear(); for(int j=0; j<bs[i].size(); j++){ if(dict[i].find(bs[i][j])==dict[i].end() || dict[i][bs[i][j]] > ps[i][j]){ dict[i][bs[i][j]] = ps[i][j]; } } } for(int i=0; i<N; i++){ int tmp = 1<<30; for(map<int,int>::reverse_iterator itr=dict[i].rbegin(); itr!=dict[i].rend(); itr++){ tmp = min(tmp, itr->second); itr->second = tmp; } } set<int> limits; for(int i=0;i<N;i++){ for(map<int,int>::iterator itr=dict[i].begin(); itr!=dict[i].end(); itr++){ int limit = itr->first; bool ok = true; for(int j=0; j<N; j++)if(dict[j].rbegin()->first < limit) ok = false; if(ok) limits.insert(limit); } } double ret = 0; for(set<int>::iterator itr=limits.begin(); itr!=limits.end(); itr++) ret = max(ret, check(*itr)); return ret; } int main(){ int T; scanf("%d",&T); while(T--){ scanf("%d",&N); for(int i=0; i<N; i++){ int m, b, p; bs[i].clear(); ps[i].clear(); scanf("%d",&m); for(int j=0; j<m; j++){ scanf("%d%d",&b,&p); bs[i].push_back(b); ps[i].push_back(p); } } printf("%.3f\n",solve()); } return 0; }