FOJ 1887 景区摊位安排问题
http://acm.fzu.edu.cn/problem.php?pid=1887
按照题目要求先求出每个联通分支,然后在每个联通分支里面按照单位花费,从小到大排序,贪心一下就行了。
#include <iostream>
#include <cstdio>
#include <string.h>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
const int maxn = 105;
struct node
{
double x;
double y;
int vnum;
int tnum;
int pnum;
int cost;
}a[maxn];
int vis[maxn];
bool operator < (node p,node q)
{
return p.cost>q.cost;
}
priority_queue<node>pq;
vector<int>v[maxn];
int n=0,sum1=0,sum2=0;
double r=0;
const double eps = 1e-8;
double Dist(int i,int j)
{
return sqrt( (a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y));
}
void dfs(int t)
{
vis[t]=1;
sum1+=a[t].pnum;
sum2+=a[t].vnum;
pq.push(a[t]);
for(int i=1;i<=n;i++)
{
if(vis[i]==1 || Dist(t,i)>r+eps)
continue;
dfs(i);
}
}
int main()
{
int t=1,T,maxp=0,minc=0;
scanf("%d",&T);
while(T--)
{
maxp=0;
minc=0;
scanf("%d %lf",&n,&r);
for(int i=1;i<=n;i++)
scanf("%lf %lf %d",&a[i].x,&a[i].y,&a[i].vnum);
for(int i=1;i<=n;i++)
scanf("%d %d",&a[i].tnum,&a[i].cost);
for(int i=1;i<=n;i++)
scanf("%d",&a[i].pnum);
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{
if(vis[i]==1)
continue;
while(pq.size()>0)
pq.pop();
sum1=0;
sum2=0;
dfs(i);
if(sum2>=sum1)
{
maxp+=sum1;
continue;
}
maxp+=sum2;
sum1-=sum2;
while(pq.size()>0 && sum1>0)
{
node tmp = pq.top();
pq.pop();
if(sum1>=tmp.tnum)
{
sum1-=tmp.tnum;
maxp+=tmp.tnum;
minc+=tmp.cost*tmp.tnum;
}
else
{
maxp+=sum1;
minc+=tmp.cost*sum1;
sum1=0;
}
}
}
printf("Case %d: %d %d\n",t++,maxp,minc);
}
return 0;
}
浙公网安备 33010602011771号