题目链接:https://cn.vjudge.net/problem/UVA-11054
题意:
每个房子里的人,要么要买酒要么要卖酒,保证所有卖酒的量和买酒的量之和为0,也就是供应量一定是足够的;一桶酒运到一个相邻的房子要一个劳动力,问最少要多少劳动力才能完成运送任务;
思路:(codeforces div2 的ABC很多都是这样的题)
第一种:从第一个开始,如果想要卖酒,那么就从当前位置开始找最近的需要买酒的人,如果买酒的量能够满足卖酒的,就从第二个开始遍历;如果不满足,就继续找下一个买酒的人,直到当前的值为0;(先暂且不看题目是怎么问你问题的,只要知道一点,就是当满足题目要求的时候,所有给出的值到最后都会变成0,所以,我们只需要考虑如何把每一个房子的对应的需求量变成0就行了,因为步数跟消耗的劳动力有关系,求最小,那肯定是优先看最近的,因为第一个值只能通过右边的值归0,所有优先把第一个变成0,那么第二个就跟第一个是一样的状态了,也是只能通过右边的值归0);
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<sstream>
#include<vector>
using namespace std;
#define IOS ios::sync_with_stdio(false); cin.tie(0);
typedef long long ll;
const int Maxn = 1e5+10;
const long long LINF = 1e18;
const int INF = 0x3f3f3f3f;
int a[Maxn];
int main (void)
{
int n;
while (scanf("%d",&n) != EOF) {
if(!n) break;
for (int i = 1; i <= n; ++i) {
scanf("%d",&a[i]);
}
ll res = 0;
int tmp;
for (int i = 1; i < n; ++i) {
if(a[i] == 0) continue;
tmp = a[i];
if(tmp < 0) {
for (int j = i+1; j <= n; ++j) {
if(a[j] > 0) {
if(tmp+a[j] < 0) {
tmp+=a[j];
a[j] = 0;
} else {
a[j]+=tmp;
tmp = 0;
}
res+=(j-i)*abs(a[i]-tmp);
a[i] = tmp;
if(tmp == 0) break;
}
}
}
else if(tmp > 0) {
for (int j = i+1; j <= n; ++j) {
if(a[j] < 0) {
if(tmp+a[j] > 0) {
tmp+=a[j];
a[j] = 0;
} else {
a[j]+=tmp;
tmp = 0;
}
res+=(j-i)*abs(a[i]-tmp);
a[i] = tmp;
if(tmp == 0) break;
}
}
}
}
printf("%lld\n",res);
}
return 0;
}
第二种(紫书的方法):
第一个房子不管是买酒还是卖酒,来源或者运出去一定通过第二个房子,不管这些酒是不是第二个房子产的或者是第二个房子需要的;比如说,第一个房子要买酒,假设最优的方法是取第三个房子的酒,那么运输的过程中,是不是一定会经过第二个房子?所以我不管第一个房子是卖酒还是买酒,我直接把需求量全部丢给第二个房子,那么第二个房子有可能会从卖酒变成买酒也可能仍然是卖酒,如果第二个房子能正好满足需求就最好,如果不能就继续把需求丢给第三个房子,到最后,所有的值都会变成0,而且每一步都只运输一个房子,我们要做的就是把多余的,丢出去的需求量加起来就行了,这样遍历一次,就能把每一个都值都归0;
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<sstream>
#include<vector>
using namespace std;
#define IOS ios::sync_with_stdio(false); cin.tie(0);
typedef long long ll;
const int Maxn = 1e5+10;
const long long LINF = 1e18;
const int INF = 0x3f3f3f3f;
int main (void)
{
int n;
while (cin >> n && n) {
ll ans = 0, a, last = 0;
for (int i = 0; i < n; ++i) {
cin >> a;
ans+=abs(last);
last+=a;
}
cout << ans << endl;
}
return 0;
}