POJ1701

Dissatisfying Lift
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 4906 Accepted: 1065

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
解答:
这到题的通过率不高,首先难度在于推公式,再次是高精度,幸好这个题可以直接用__int64,就过了。
下午看到这道题的时候,比较懒,想直接一个个遍历,求出下楼的不满总数&上楼的不满总数,时间复杂是O(N^2);而且没有考虑道高精度,所以直接就WA和TLE了。
晚上回来,去31号楼,推了一个小时,总算把公式推出来了。
令: pi = f[1] + f[2] ...... f[i]
          down[0] = 0;
          down[i+1] = down[i] + b*pi + (p1+p2 ....+ pi-1);
     
          qi = f[m] + f[m-1] + ...f[m-i];
          up[m] = 0;
          up[i-1] = up[i] + a* qi + (q1 + q2 ...+qi-1);
这个公式的和行就是后面的求和部分,(q1 + q2 ...+qi-1);
源代码:
#include <iostream>
using namespace std;
__int64 num[10005], up[10005], down[10005], f[10005];
int main()
{
    int t, m, a, b, sum0, sum1, ans;
    int i;
    cin>>t;
    while(t--)
 {
        cin>>m>>a>>b;
        for (i = 1; i <= m; i++) 
   scanf("%l64d",&num[i]); //输入每层楼的人数
        sum0 = num[1];
  sum1 = 0; 
  down[1] = 0; //在1楼停下楼不满意度为0
        for (i = 2; i <= m; i++) 
  {
            down[i] = down[i - 1] + b * sum0 + sum1; //求出在各楼停下楼的不满意度
            sum1 += sum0;
   sum0 += num[i];
        }
        sum0 = num[m];
  sum1 = 0; 
  up[m] = 0;//停在第m层上楼不满意度为0
        for (i = m - 1; i >= 1; i--)
  {
            up[i] = up[i + 1] + a * sum0 + sum1; //求出停在各楼的上楼不满意度
            sum1 += sum0; sum0 += num[i];
        }
        ans = 1;
        for (i = 1; i <= m; i++)
  {
            num[i] = up[i] + down[i];
            if (num[ans] > up[i] + down[i]) ans = i;
        }
        cout<<ans<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值