「美团 CodeM 初赛 Round A」倒水

贪心???

题目描述
有一个大水缸,里面的水温度为T单位,体积为C升。另有n杯水,每杯的温度为ti单位,体积为ci升,现在你要将大水缸的水倒入n杯水中使得n杯水的温度相同(不一定倒完),请问这是否可能?如果可能,输出可以达到的最高温度。

注意:一杯温度为t1单位,体积为c1升的水与一杯温度为t2单位,体积为c2升的水混合后的温度为(t1c1+t2c2)/(c1+c2)单位,体积为c1+c2升。

输入格式
第一行一个整数n。 第二行两个整数T,C。 接下来nn行每行两个整数ti,ci,分别表示温度与体积。

输出格式
如果不可能,输出Impossible,否则第一行输出Possible,第二行输出最高温度(保留4位小数)

样例数据
input

3
10 2
20 1
25 1
30 1
output

Possible
20.0000
数据规模与约定
时间限制:1s
空间限制:256M
本题有部分分,正确输出第一行得到当前测试点40%的分数

对于60%的数据:n≤100 ; T,ti≤10n≤100 ; T,ti≤10
对于100%的数据:n≤105 ; 0≤T,ti≤104 ; 0≤C≤109

思路:分三种情况讨论。
1.max(a[i])>t>min(a[i]) 直接输出Impossible。因为不论怎么加水,温度只会无限趋近于t而达不到t,n杯水的温度不可能相等。
2.min(a[i])>=t 此时加水只会让温度降低,因此只有温度为min(a[i])时才能相等,计算所有水温度降至min(a[i])所需的水的量,然后与c比较。若大于c则为Impossible,否则最大温度为min(a[i])。
3.max(a[i])<=t 此时加水会让温度升高,先计算所有水温度到达max(a[i])所需的水的量,若c仍有剩余,就把剩下的都加进去,计算最后的温度即为答案。

注意特判max[i]=t和min[i]=t的情况,不然会RE(除以0)

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 100000
using namespace std;
int t,n,ma,mi=0x7fffffff;
double c;
int a[MAXN+5],b[MAXN+5];
int main(){
    scanf("%d",&n);
    scanf("%d%lf",&t,&c);
    int now=c,ss=0;
    for (int i=1;i<=n;i++){
        scanf("%d%d",&a[i],&b[i]);
        ss+=b[i]; ma=max(ma,a[i]); mi=min(mi,a[i]);
    }
    if (mi<t&&ma>t){
        printf("Impossible\n");
        return 0;
    }
    if (mi>=t){
        bool flag=false;
        for (int i=1;i<=n;i++){
            double x;
            if (mi!=t) x=(a[i]-mi)*b[i]/(mi-t);
            c-=x;
            if (c<0){
                flag=true;
                break;
            }
        }
        if (flag){
            printf("Impossible\n");
            return 0;
        }
        else{
            printf("Possible\n");
            double ans=mi;
            printf("%.4lf\n",ans);
            return 0;
        }
    }
    if (ma<=t){
        bool flag=false;
        for (int i=1;i<=n;i++){
            double x;
            if (ma!=t) x=(ma-a[i])*b[i]/(t-ma);
            c-=x;
            if (c<0){
                flag=true;
                break;
            }
        }
        if (flag){
            printf("Impossible\n");
            return 0;
        }
        else{ 
            printf("Possible\n");
            double ans=ma;
            double sum=now+ss-c;
            if (c){
                ans=(ma*sum+c*t)/(sum+c);
            }
            printf("%.4lf\n",ans);
            return 0;
        }
    }
    return 0;
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值