P1984 [SDOI2008]烧水问题(具体证明)

传送门

我见过的第二恶心的题,第一是糖果传递...

以下是一堆具体的证明,自己想的,可能考虑不周,不想看也可以直接看结论


首先有一个很显然的贪心,烧开的水要尽量把热量传递出去

所以有一个比较显然的方法:每杯水烧开后都与下一杯水热传递,平衡后再把剩下的温度与更后面一杯水热传递,这样一直下去...

十分显然把热量传递出去比不传递出去要更优

具体证明:设下一杯水温度为 $t_1$,此时上一杯水已经烧开,为$t_{max}$

如果它们之间进行热传递,那么下一杯水的热量就变成 $frac{t_1+t_{max}}{2}$

显然温度会更高,所以烧开所需热量更少,答案会更优,并且可以容易推广到多杯水的情况

然后热量传出去了,按什么顺序烧开他们也是关键

方法:把温度从大到小排序,优先烧温度大的水再把热量传下去会更优

证明:设第一杯水温度为 $t_1$ ,第二杯水温度为 $t_2$,且 $t_1>t_2$

如果我们先烧第一杯水,那么需要升高的温度为 $t_{max} - t_1$ 

然后第一杯水烧开后再把热量传给第二杯水,第二杯水温度变成 $frac{t_2+t_{max}}{2}$

把第二杯水烧开需要升高的温度为 $t_{max} - frac{t_2+t_{max}}{2}$

因为水质量一样,所以升高的温度可以直接相加,化简得$frac{3}{2}t_{max} - t_1 -frac{t_2}{2}$

因为水的质量一样,所以温度的升高多少就相当于热量的消耗多少

如果我们先烧第二杯水再传温度给第一杯水再烧第一杯水

经过同样的方法可以算出总共升高的温度为$frac{3}{2}t_{max} - t_2 -frac{t_1}{2}$

因为 $t_1>t_2$ ,所以第一种方案更优,此结论用同样的方法也能推广到多杯水的情况


所以总结一下,就是优先烧温度大的水,然后把热量尽量传出去

知道了方案,每杯水消耗的热量自己找找规律就出来了

设 $f_n$ 表示第 n 杯水烧开消耗的热量

那么 $f_n=f_{n-1}*[1-frac{1}{2}(n-1)]$

代码不解释

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
    return x*f;
}
int n;
double ans,now=420000.0;
int main()
{
    n=read(); now/=n;
    for(int i=1;i<=n;i++) ans+=now,now*=(1-0.5/i);
    printf("%.2lf",ans);
    return 0;
}

 

原文地址:https://www.cnblogs.com/LLTYYC/p/9828420.html