Robotruck UVALive - 3983 撿垃圾的機器人 單調隊列優化dp

 題目鏈接

This problem is about a robotic truck that distributes mail packages to several locations in a factory. The robot sits at the end of a conveyer at the mail office and waits for packages to be loaded into its cargo area. The robot has a maximum load capacity, which means that it may have to perform several round trips to complete its task. Provided that the maximum capacity is not exceeded, the robot can stop the conveyer at any time and start a round trip distributing the already collected packages. The packages must be delivered in the incoming order.

     The distance of a round trip is computed in a grid by measuring the number of robot moves from the mail office, at location (0,0), to the location of delivery of the first package, the number of moves between package delivery locations, until the last package, and then the number of moves from the last location back to the mail office. The robot moves a cell at a time either horizontally or vertically in the factory plant grid. For example, consider four packages, to be delivered at the locations (1,2), (1,0), (3,1), and (3,1). By dividing these packages into two round trips of two packages each, the number of moves in the first trip is 3+2+1=6, and 4+0+4=8 in the second trip. Notice that the two last packages are delivered at the same location and thus the number of moves between them is 0.

     Given a sequence of packages, compute the minimum distance the robot must travel to deliver all packages.

分析:首先設 d[ i ] 爲處理到第 i 個垃圾所用的最小距離,那麼很容易想到動態轉移方程:d[ i ] = min { d[ j ] + dist2origin( j + 1 )  +  dist( j + 1 , i ) + dist2origin( i ) }  且 w( j + 1 , i )  <= W , 解釋一下:dist( i )  爲 i 點到原點的距離(指哈密頓距離),dist( j + 1 ,i) 代表 從j + 1 到 i 的距離和。w(j + 1 , i ) 爲從 j + 1 到 i 的重量和。W 爲最大重量。

轉化動態方程了:我們用前綴和的思想分別記錄前綴距離和前綴重量,分別用數組 total_dist[ i ] ,total_weight[ i ] ,d[ i ] 爲點i 到原點的距離,這樣方程就可以變爲:

                dp[ i ] = min { d[j] - total_dist[j+1] + dist2origin[j+1] } 且 total_weight[ i ] - total_weight[ j ] <= W ;變成這樣後你會發現前面的各個數只與本身相關,可以把他們放入一個隊列中,只要維護隊列的最小值(在重量滿足的前提下).

#include<cstdio>
#include<algorithm>
using namespace std;

const int maxn = 100000 + 10;

int x[maxn], y[maxn];
int total_dist[maxn], total_weight[maxn], dist2origin[maxn];
int q[maxn], d[maxn];

int func(int i) {
  return d[i] - total_dist[i+1] + dist2origin[i+1];
}

main() {
  int T, c, n, w, front, rear;
  scanf("%d", &T);
  while(T--) {
    scanf("%d%d", &c, &n);
    total_dist[0] = total_weight[0] = x[0] = y[0] = 0;
    for(int i = 1; i <= n; i++) {
      scanf("%d%d%d", &x[i], &y[i], &w);
      dist2origin[i] = abs(x[i]) + abs(y[i]);
      total_dist[i] = total_dist[i-1] + abs(x[i]-x[i-1]) + abs(y[i]-y[i-1]);
      total_weight[i] = total_weight[i-1] + w;
    }
    front = rear = 1;
    for (int i = 1; i <= n; i++) {
      while (front <= rear && total_weight[i] - total_weight[q[front]] > c) front++;
      d[i] = func(q[front]) + total_dist[i] + dist2origin[i];
      while (front <= rear && func(i) <= func(q[rear])) rear--;
      q[++rear] = i;
    }
    printf("%d\n", d[n]);
    if(T > 0) printf("\n");
  }
  return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章