ZOJ 3031 Robotruck (dp + 单调队列)

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=2029

  搞了一个多小时的一道DP&&单调队列题。这题在ACM-ICPC Live Archive中有相似的一题,不过在LA中,每个位置的物品重量不为0,这样就限制了寻找上一层dp值的范围只在下标为i-100~i 之间,复杂度是O(CN)。可是到了ZOJ,dp值的寻找就有可能要把之前所有已经处理的状态都找一遍,这样子,同样的做法就果断超时了。

  不过可以轻易的发现,dp是线性的,而且最优值是可以通过某种转换方式表示出来。同时,因为物品的发放顺序有所限制,所以可以直接用前缀和来快速找到某个区间的距离之和。

代码如下:

View Code
 1 LL dp, wSum[N], dSum[N];
 2 int x[N], y[N];
 3 
 4 void input(int n) {
 5     LL w;
 6     wSum[0] = dSum[0] = 0ll;
 7     REP_1(i, n) {
 8         scanf("%d%d%lld", &x[i], &y[i], &w);
 9         wSum[i] = wSum[i - 1] + w;
10         dSum[i] = dSum[i - 1] + abs(x[i] - x[i - 1]) + abs(y[i] - y[i - 1]);
11     }
12 }
13 
14 PRIQ<pair<LL, int>, vector<pair<LL, int> >, greater<pair<LL, int> > > Q;
15 
16 LL work(int n, int w) {
17     int p = 1;
18     while (!Q.empty()) Q.pop();
19     Q.push(MPR(abs(x[1]) + abs(y[1]) - dSum[1], 0));
20     REP_1(i, n) {
21         while (wSum[i] - wSum[p - 1] > w) p++;
22         while (Q.top().SE + 1 < p) Q.pop();
23         LL fi = Q.top().FI;
24         dp = fi + abs(x[i]) + abs(y[i]) - (dSum[i + 1] - dSum[i]) + abs(x[i + 1]) + abs(y[i + 1]);
25         Q.push(MPR(dp, i));
26     }
27     dp += dSum[n] - abs(x[n + 1]) - abs(y[n + 1]) + (dSum[n + 1] - dSum[n]);
28     return dp;
29 }
30 
31 int main() {
32     int T, n, m;
33     while (~scanf("%d", &T)) {
34         while (T--) {
35             scanf("%d%d", &m, &n);
36             input(n);
37             cout << work(n, m) << endl;
38         }
39     }
40     return 0;
41 }

 

——written by Lyon

转载于:https://www.cnblogs.com/LyonLys/archive/2013/02/19/zoj_3031_Lyon.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值