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;
}