POJ 2940 Wine Trading in Gergovia【贪心】

来源:互联网 发布:artrage for mac 编辑:程序博客网 时间:2024/04/29 22:36

Wine Trading in Gergovia
Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 3206 Accepted: 1462

Description

As you may know from the comic “Asterix and the Chieftain’s Shield”, Gergovia consists of one street, and every inhabitant of the city is a wine salesman. You wonder how this economy works? Simple enough: everyone buys wine from other inhabitants of the city. Every day each inhabitant decides how much wine he wants to buy or sell. Interestingly, demand and supply is always the same, so that each inhabitant gets what he wants.

There is one problem, however: Transporting wine from one house to another results in work. Since all wines are equally good, the inhabitants of Gergovia don’t care which persons they are doing trade with, they are only interested in selling or buying a specific amount of wine. They are clever enough to figure out a way of trading so that the overall amount of work needed for transports is minimized.

In this problem you are asked to reconstruct the trading during one day in Gergovia. For simplicity we will assume that the houses are built along a straight line with equal distance between adjacent houses. Transporting one bottle of wine from one house to an adjacent house results in one unit of work.

Input

The input consists of several test cases.

Each test case starts with the number of inhabitants n (2 ≤ n ≤ 100000). The following line contains n integers ai (−1000 ≤ ai ≤ 1000). If ai ≥ 0, it means that the inhabitant living in the ith house wants to buy ai bottles of wine, otherwise if ai < 0, he wants to sell −ai bottles of wine. You may assume that the numbers ai sum up to 0.

The last test case is followed by a line containing 0.

Output

For each test case print the minimum amount of work units needed so that every inhabitant has his demand fulfilled. You may assume that this number fits into a signed 64-bit integer (in C/C++ you can use the data type “long long” or “__int64”, in JAVA the data type “long”).

Sample Input

55 -4 1 -3 16-1000 -1000 -1000 1000 1000 10000

Sample Output

99000

Source

Ulm Local 2006

题目大意:有n个店铺,负值为出售a【i】个瓶子,正值为想要购买a【i】个瓶子,你是一个搬运工,从j店铺买x个瓶子送到i店铺需要消耗fabs(j-i)*x的体力,问最小体力花费。

解法:因为想要购买的和想要出售的瓶子数一定是相等的,所以我们不用多考虑其他问题,一门心思贪心就好。那么要如何贪心呢?

我们从第一组样例中很容易看的出来我们要怎样来分配最合适:

2号店铺的4个瓶子搬运到1号那里,消耗1*4体力、然后变成:

1 0 1 -3 1

3号店铺的4个瓶子搬运到1、3、4那里,消耗1*1+1*1+1*3=5体力、然后变成

0 0 0 0 0达到目的,一共最小的消耗体力数值为9;

我们这里考虑的方向是正方向思维,从卖东西那里搬运到需要买东西那里,而且贪心的点在于:从负的那里搬到距离他自己最近的正的那里。这样一门心思的贪是很难做通这个题目的。我们不妨换个思路来想:既然我需要买东西,我是可以让搬运工从卖东西那里给我搬运过来。这个时候搬运工就有两个工作方向了:

1、从卖东西那里搬东西给买东西的那里、

2、在买东西那里接到任务从卖东西那里给他进东西到他这里、

两个方向同时贪心+卖东西数==买东西数,我们可以确定的思路就是这样的:

遍历每一个店铺(0<=i<=n),然后找他后边的店铺,如果是买东西找卖东西的店铺,如果是卖东西找买东西的店铺,把每一个i都弄成0,我们就答到了最终目的。

那么这个思路是否正确呢?答案是对的,那么这个思路是否会AC呢?答案是否定的,直接暴力两层for是会TLE的。

这个时候我们控制两个变量i,j。这里我规定i是标记买东西的店铺,j是规定卖东西的店铺,对于每个i,j。我们找到min( a【i】,-a【j】),使得一方变成0,之后i,j向后扫,如果j控制的店铺变成了0,我们就让j继续向后找,早晚会使得a【i】变成0,然后i再向后扫,使得a【j】变成0,最终达到全部变成0的目标。

贪心完毕、

AC代码:

#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>#include<math.h>using namespace std;#define ll long long intll a[121212];int main(){    int n;    while(~scanf("%d",&n))    {        if(n==0)break;        int cont=0;        for(int i=1;i<=n;i++)        {            scanf("%lld",&a[i]);        }        int i=1;        int j=1;        ll output=0;        while(1)        {            while(i<=n&&a[i]<=0)            i++;            while(j<=n&&a[j]>=0)            j++;            if(i>=n+1||j>=n+1)break;            int work=min(a[i],-a[j]);            a[i]-=work;            a[j]+=work;            output+=work*fabs(j-i);        }        printf("%lld\n",output);    }}









1 0
原创粉丝点击