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; }