模拟题:流量问题

Problem H: 流量问题

Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 36 Solved: 11
[Submit][Status][Web Board]
Description

远岛君在理科大楼五楼闲着无事,闲逛到了女厕所,发现有一个底面为1×W,高为无限大的一个没有顶盖的空水箱放在平坦的地面上,中间从左到右竖直地插入了W-1块木板,每块木板之间的间隔为1,且这些木板的高度从左到右为非递增。

由于远岛君非常无聊,于是他沿着水箱最左侧倒入一定量的水,水会沿着物理规律流动(水面可能会高于某些隔板)。水箱最左边和最右边可以看成是两块高为无穷大的隔板。你能告诉他最终的水箱状态吗?

Input

第一行只有一个整数T(T≤100),表示测试数据组数。
第二行有两个整数W,V,本别代表水箱宽度和倒入水的体积,W不超过10,V不超过1000.
第三行有W-1个整数,分别代表第i块隔板的高度hi,该高度序列非递减。hi不超过500.

Output

每个测试数据输出一行,共W个小数,分别表示第i块水柱的高度,该高度取到小数点后一位即可,相邻数字用空格隔开

Sample Input

2
4 8
3 2 1
4 12
3 2 1
Sample Output

3.0 2.0 1.5 1.5
3.0 3.0 3.0 3.0

AC代码:

#include<cstdio>
const int maxn = 15;
double ans[maxn];
double h[maxn];
double p[maxn];
const double INF = 1.0 * 0x3f3f3f3f;
const double eps = 1e-8;
int main()
{
    int t,w;
    double v,sum;
    scanf("%d", &t);
    while (t--)
    {
        sum = 0;
        for (int i = 0; i < maxn; i++)
        {
            ans[i] = 0;
            p[i] = 0;
        }
        scanf("%d %lf", &w, &v);
        if (w == 1)
        {
            printf("%.1lf\n",v);
            continue;
        }
        for (int i = 1; i <= w-1; i++)
        {
            scanf("%lf", &h[i]);
            sum += h[i];
        }
        h[w] = h[w-1];
        sum += h[w];
        if (v < sum + eps)
        {
            for (int i = 1; i <= w; i++)
            {
                if (v > h[i] - eps)
                {
                    ans[i] = h[i];
                    v -= h[i];
                }
                else
                {
                    ans[i] = v;
                    break;
                }
            }
            for (int i = 1; i < w; i++)
                printf("%.1lf ",ans[i]);
            printf("%.1lf\n",ans[w]);
            continue;
        }
        for (int i = 1; i <= w; i++) ans[i] = h[i];
        v -= sum;
        h[0] = INF;
        for (int i = w-1; i >= 1; i--)
        {
            p[i] = p[i+1] + ((h[i-1] - h[i]) * (w-i+1));
        }
        int k;
        for (k = w-1; k >= 1; k--)
        {
            if (v < p[k] + eps)
                break;
        }
        double tmp = 0;
        for (int i = k; i <= w; i++)
        {
            tmp += h[i];
        }
        double newH = (v+tmp) / (w-k+1);
        for (int i = k; i <= w; i++) ans[i] = newH;
        for (int i = 1; i < w; i++)
        {
            printf("%.1lf ",ans[i]);
        }
        printf("%.1lf\n",ans[w]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值