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;

}

 

 

你可能感兴趣的:(问题)