一直想做一道扫描法的题,终于。。here it is。。
不明白为什么这道题在uva数据那么惨。不是很难的吧。。16xx那么难可数据那么好看一定是因为根本就没人做!全是测试号的数据!最近被16xx的题恶心坏啦
这个题就是从前往后扫描,扫的时候记录下到目前为止的最高木板和位置就好了。在跨越中点后,分几种情况讨论下就好了。主要是注意好跨中点的高度相等的木板。
比起UVa#1610 Party Game (习题8-2),分类讨论的规模不算很恶心。
Run Time: 0.016s
#define UVa "8-24.10366.cpp" //Faucet Flow
#include<cstring>
#include<cstdio>
#include<vector>
using namespace std;
struct Divider {
int h, x;
Divider(int a, int b):h(a),x(b){}
};
//Global Variables.
const int maxn = 1000 + 10;
int leftx, rightx;
vector<Divider> v;
int main() {
while(scanf("%d%d", &leftx, &rightx) && leftx) {
int a, i;
v.clear();
for(int i = leftx; i <= rightx; i += 2) {
scanf("%d", &a);
v.push_back(Divider(a, i));
}
int rcdh = v[0].h, rcdx = v[0].x;
long long ans1 = 0, ans2 = 0;
for(i = 1; i < v.size(); i ++) { //left->right
Divider& d = v[i];
if(d.h > rcdh) {
ans1 += rcdh * (d.x - rcdx);
if(d.x * rcdx < 0) break;
rcdh = d.h;
rcdx = d.x;
}
else if(d.h == rcdh) {
if(d.x*rcdx < 0) { //opposite side. same side: ignore.
int j = i + 1;
while(j < v.size() && v[j].h <= d.h) j ++;
if(j == v.size()) { //no higher dividers through other end.
long long tmp = v[v.size() - 1].x - d.x;
tmp *= d.h;
ans1 += min(tmp, ans1);
ans1 += d.h * (d.x - rcdx);
}
else {
long long tmp = v[j].x - d.x;
tmp *= d.h;
ans1 += min(tmp, ans1);
ans1 += d.h * (d.x - rcdx);
}
break;
}
else {
ans1 += (d.x - rcdx) * d.h;
rcdx = d.x;
}
}
}
if(i == v.size() && rcdx < 0) ans1 = 10000000000000L;
i = v.size() - 1;
rcdh = v[i].h, rcdx = v[i].x;
for(i = v.size() - 1; i >= 0; i --) { //right->left
Divider& d = v[i];
if(d.h > rcdh) {
ans2 += rcdh * (rcdx - d.x);
if(d.x * rcdx < 0) break;
rcdh = d.h;
rcdx = d.x;
}
else if(d.h == rcdh) {
if(d.x*rcdx < 0) { //opposite side. same side: ignore.
int j = i - 1;
while(j >= 0 && v[j].h <= d.h) j --;
if(j == -1) { //no higher dividers through other end.
long long tmp = d.x - v[0].x;
tmp *= d.h;
ans2 = ans2 + min(tmp, ans2); //min: if leaking to other side is better, do it.
ans2 += d.h * (rcdx - d.x);
}
else {
long long tmp = d.x - v[j].x;
tmp *= d.h;
ans2 = ans2 + min(tmp, ans2);
ans2 += d.h * (rcdx - d.x);
}
break;
}
else {
ans2 += (rcdx - d.x) * d.h;
rcdx = d.x;
}
}
}
if(i == -1 && rcdx > 0) ans2 = 10000000000000L;
printf("%lld\n", min(ans1, ans2));
}
return 0;
}