Dissatisfying Lift

Dissatisfying Lift

Description

There's a building with M floors. The amounts of tenants of every floor are K1, K2, K3, ..., Km. One day all the tenants went home together and they took the same lift (suppose the lift was large enough). Because of some reason the lift could only stop on one floor and the tenants must go upstairs or downstairs to their houses. Every tenant went up N floors would make the dissatisfied degree rise N * a + 0.5 * N * (N - 1) degrees, and every tenant went down N floors would make the dissatisfied degree rise N * b + 0.5 * N * (N - 1) degrees. Your task is to tell which floor the lift should stop, in order to make the dissatisfied degree as low as possible.

Input

The first line of the input contains a single integer T (1 <= T <= 20), the number of test cases. Then T cases follow. The first line of each test contains M (1 <= M <= 10000), a and b (0 <= a, b <= 100). The second line contains K1, K2, K3, ..., Km (0 <= Ki <= 20, i = 1..M).

Output

For each test case, print a line containing a single integer, indicating which floor the lift should stop.

Sample Input

1
5 3 2
1 1 1 1 1

Sample Output

3
http://poj.org/problem?id=1701
解题思路:先把题目分拆为两个部分,一部分为每一层楼租客下楼的愤怒值,另一部分为每一层楼租客上楼的愤怒值,利用数学推理,推导出下楼和上楼的愤怒值累加公式,通过两个for循环分别求出每一层楼租客的上楼或下楼的愤怒值,最后相加得出总愤怒值,开始设置一个足够大的数,与之比较,求出总愤怒值最小值所在楼层即为所求解。
 
#include <iostream>
using namespace std;

const int MAX=10001;

int main()
{
	int f[MAX],T,M,a,b;
	int i;
	__int64 down[MAX],up[MAX],min,k;
	cin>>T;
	while(T--)
	{
		memset(f,0,sizeof(f));
		memset(down,0,sizeof(down));
		memset(down,0,sizeof(up));
		cin>>M>>a>>b;
		for (i=1;i<=M;i++)
			cin>>f[i];
		int p,q;
		__int64 sum=0;
		p=f[1];q=f[M];
		down[1]=0;
		for (i=2;i<=M;++i)
		{
			down[i]=down[i-1]+b*p+sum;
			sum+=p;
			p+=f[i];
		}
		sum=0;
		up[M]=0;
		for (i=M-1;i>=1;--i)
		{
			up[i]=up[i+1]+a*q+sum;
			sum+=q;
			q+=f[i];
		}
		min=99999999999999;
		int bestf=0;
		for (i=1;i<=M;i++)
		{
			k=down[i]+up[i];
			if (min>k)
			{
				min=k;
				bestf=i;
			}
		}
		cout<<bestf<<endl;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值