codeforces-801C

题目来源:http://codeforces.com/problemset/problem/801/C

刚看到题目的时候就想着排序贪心做,但做到时间时,发现可以二分找时间,结果二分(也得注意一下细节)(写代码的时候务必静心!)和贪心都没写出来,感觉二分做的比较正,贪心也是思维(暴力......,因为n也不太大)的一种拓展吧....。附上二分和贪心的代码。

贪心:

如果排序完后,前i个在充电的情况下能够达到i+1个的时间,就把i+1加起来。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n;
double k,p;
struct A {
	double a,b,t;
}c[100100];
bool cmp(struct A t1,struct A t2)
{
	if(t1.t==t2.t)
	return t1.a<t2.a;
	else
	return t1.t<t2.t;
}
int main()
{
	int i,j;
	cin>>n>>p;
	double sum=0.0;
	for(i=0;i<n;i++)
	{
		cin>>c[i].a>>c[i].b;
		c[i].t=c[i].b/c[i].a;
		sum+=c[i].a;
	}	
	if(sum<=p)//每秒消耗的小于等于补充的因为换的时间题目说了忽略不计 毫无疑问 
	{
		printf("-1");
		return 0;
	}
	sort(c,c+n,cmp);//对时间进行排序,从小到大 
 	double pow=c[0].t*p,dec=c[0].a,ans=0.0;
    for(i=0;i<n-1;i++)
    {
        if(pow+(c[i+1].t-c[i].t)*p>(c[i+1].t-c[i].t)*dec)
        {
            pow+=(c[i+1].t-c[i].t)*(p-dec),dec+=c[i+1].a;
        }
        else
        {
            break;
        }
    }
    ans=pow/(dec-p);//多余的能量除以消耗的能量等于延续的时间
    ans+=c[i].t;//加初始的时间
    printf("%.8f\n",ans);
	return 0;
} 

二分:

若运算完还有能量可以继续充电,则继续扩大时间,若小于并等于需要继续减小。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
double n,k,p;
struct A {
	double a;
	double b;
	double v;
}c[100100];
double pd(double t)
{
	int i,j;
	double sum=p*t;
	for(i=0;i<n;i++)
	{
		double temp=c[i].b-c[i].a*t;
		if(temp<0)
		sum+=temp;
	}
	return sum;
 } 
int main()
{
	int i,j;
	cin>>n>>p;
	double sum=0.0;
	for(i=0;i<n;i++)
	{
		cin>>c[i].a>>c[i].b;
		sum+=c[i].a;
	}
	if(sum<=p)
	{
		printf("-1");
		return 0;
	}
	double l=0,r=1e10,mid;
	while(l+1e-4<=r)//小数的一般都带精确的值
	{
		mid=(l+r)/2;
		if(pd(mid)>0)//等于0时的恰好
		l=mid;
		else
		r=mid;
	}
	printf("%.8lf",mid);
	return 0;
} 
发布了56 篇原创文章 · 获赞 17 · 访问量 2350

猜你喜欢

转载自blog.csdn.net/weixin_43958964/article/details/98383771