http://www.cnblogs.com/iRedBean/p/5975480.html
像这种O(n^2)匹配的问题一般可以用优先队列,集合或者多重集合优化成O(nlogn)。
贪心的思路很简单,先尝试匹配,然后每个socket添加一个adapter,继续,重复31次。最多加三十次就变成1了。
这么贪心为什么对呢。
添加adapter后的socket匹配潜力肯定是减弱了的。这一轮无法匹配,加了adapter后就更难匹配了。因此不得已不加adapter。
我们又希望总的adapter最少,这也是能同时满足的。
#include<bits/stdc++.h>
#define maxn 200010
using namespace std;
struct pc
{
int pow;
int id;
pc(int a,int b):pow(a),id(b){}
friend bool operator< (const pc& a, const pc& b)
{
return a.pow<b.pow;
}
};
int n,m;
int s[maxn];
int matchp[maxn];
int matchs[maxn];
int adp[maxn];
multiset<pc>p;
int main()
{
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
int temp;
scanf("%d",&temp);
p.insert(pc(temp,i));
}
for(int i=1;i<=m;i++)
scanf("%d",&s[i]);
int sum=0;
int cnt=0;
for(int i=0;i<31;i++)
{
for(int j=1;j<=m;j++)
{
if(matchs[j]) continue;
multiset<pc>::iterator it=p.find(pc(s[j],0));
if(it!=p.end())
{
matchp[it->id]=j;
matchs[j]=it->id;
sum+=i;
cnt++;
adp[j]=i;
p.erase(it);
}
s[j]=(s[j]+1)>>1;
}
}
printf("%d %d\n",cnt,sum);
for(int i=1;i<=m;i++)
printf("%d ",adp[i]);
puts("");
for(int i=1;i<=n;i++)
printf("%d ",matchp[i]);
puts("");
return 0;
}