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

 

posted on 2011-08-23 18:26  lwbaptx  阅读(240)  评论(0编辑  收藏  举报

导航