• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
LyonLys
愿意在角落唱沙哑的歌 再大声也都是给你 请用心听 不要说话 Contact me via E-mail: lyon.lys@gmail.com
博客园    首页    新随笔    联系   管理    订阅  订阅

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

posted @ 2013-02-19 16:30  LyonLys  阅读(215)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3