题意: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;
}