北大ACM——Protecting the Flowers(贪心)

题意:N只牛,每只牛会吃掉d[i]朵花,将每只牛送回牛棚需要2*t[i]分钟。求最优方案,使得花儿被破坏得最少。

分析:从提供样例入手,一开始想到两种方案:
1.优先挑d[i]大的,符合样例,但是如果t[i]远大于d[i]就不合格了;
2.优先挑t[i]大的,符合样例,但是同理,如果d[i]远大于t[i]就不合格了。
后来想,应该是得挑选某一只牛,使得在搬走的过程中剩余的牛对花的破坏最小。然后受到FatMouse’sTrade影响,猜想可以求出两者的比,按比的大小进行排序,挑选,于是想办法证明猜想。
设在搬第i只牛时,当前所有牛每分钟破坏的花数量为sum,则搬走第i只牛会破坏:sum’’=(sum-d[i])×2×t[i]朵花,为了使sum’'更小,应尽量使d[i]大,t[i]小,因此可以找这样一个指标来表示:t[i]/d[i]。
稍微思考一下好像还真可以,而且还符合样例。值得一试。

伪代码如下:
int n;
long long sum=0,s;
double t[i],d[i],v[i];
scanf("%d",&n);
输入t[i],d[i],处理v[i],s;
v[i]从小到大排序(数据大,且v[i]相同时先选哪个并不影响结果,可用快排)
for(int i=0;i<=n-1;i++)
{
s=s-d[i];
sum=sum+s×2×t[i];
}
输出sum;

代码如下(真的AC了):

#include<cstdio>
using namespace std;
double d[100005],t[100005],v[100005];   //看清楚数组大小,开错了两次,runtime error两次
void qsort(int x,int y)
{
	if(y-x>1)
	{
		int i=x,j=y-1;
		double t1=v[x],t2=d[x],t3=t[x];
		while(i<j)
		{
			while(i<j&&v[j]>=t1)
			    j--;
			if(i<j)
			{
				v[i]=v[j];
				d[i]=d[j];
				t[i++]=t[j];
			}
			while(i<j&&v[i]<t1)
			    i++;
			if(i<j)
			{
				v[j]=v[i];
				d[j]=d[i];
				t[j--]=t[i];
			}
		}v[i]=t1;d[i]=t2;t[i]=t3;
		qsort(x,i);
		qsort(i+1,y);
	}
}
int main()
{
	int n;//while(1){
	
	long long sum=0,s=0;
	int i;
	scanf("%d",&n);
	for(i=0;i<=n-1;i++)
	{
		scanf("%lf %lf",&t[i],&d[i]);
		s+=d[i];
		if(d[i]==0) v[i]=2000005;
		else v[i]=t[i]/d[i];
	}
	qsort(0,n);
	//for(i=0;i<=n-1;i++)
	//    printf("%.2lf\n",v[i]);
	for(i=0;i<=n-1;i++)
	{
		s=s-d[i];
		sum=sum+s*t[i]*2;
	}
	printf("%lld\n",sum);//}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/shamansi99/article/details/87480465
今日推荐