POJ 3858 Hurry Plotter(DP)
Description
A plotter is a vector graphics printing device that connects to a computer to print graphical plots. There are two types of plotters: pen plotters and electrostatic plotters. Pen plotters print by moving a pen across the surface of a piece of paper. They can draw complex line art, including text, but do so very slowly because of the mechanical movement of the pens. In this problem, we are considering this matter of slowness for our special type of pen plotter. A discrete horizontal pen plotter can draw only horizontal line segments whose end points have discrete coordinates (integer x and y’s). The drawing method is quite simple. The pen starts its journey from the upper left corner of the page (x=y=0) and moves only right while drawing the specified lines on that row. Then, it moves back completely to the left, moves one row down (y ← y+1), and repeats this task for the second row. The same is done for the next rows. In other words, the pen can move down only when it is far on the left side (i.e. when x=0), and can have at most one left-to-right pass and at most one right-to-left pass on each row.
It takes one unit of time to move the pen one unit of length to the left (x ← x-1), or to the right (x ← x+1). This time is doubled if the pen is on the paper and is drawing a line segment. It takes no time to move one row down (when x=0).
Since it might take a long time for the plotter to draw all the given line segments, we have decided to add a new feature to our plotter: drawing time-limit. By specifying the time-limit, the plotter should draw the maximum number of lines (using the same drawing method given above) that can be drawn within that time-limit. Given the time-limit and line segments, you should find this maximum number.
It takes one unit of time to move the pen one unit of length to the left (x ← x-1), or to the right (x ← x+1). This time is doubled if the pen is on the paper and is drawing a line segment. It takes no time to move one row down (when x=0).
Since it might take a long time for the plotter to draw all the given line segments, we have decided to add a new feature to our plotter: drawing time-limit. By specifying the time-limit, the plotter should draw the maximum number of lines (using the same drawing method given above) that can be drawn within that time-limit. Given the time-limit and line segments, you should find this maximum number.
Input
The input contains multiple test cases. Each test case starts with a line containing two integers n and t. The integer n is the number of line segments (n ≤ 1000) and t is the time-limit (t ≤ 106). Each of the next n lines specifies a line segment by giving three integers y, xs, and xt. Integer y indicates the row of that line segment (0 ≤ y ≤ 2000), and xs and xt are the x-coordinates of its end points (0 ≤ xs ≤ xt ≤ 106). The line segments are disjoint and do not have any intersections. A case of n = t = 0 shows the end of input and should not be processed.
Output
Write the result of the ith test case on the ith line of output. Each line should have only one integer, indicating the maximum number of line segments that can be drawn in its corresponding test case.
题目大意:有n条水平的横线,每条横线都有一个纵坐标,和横线的开始横坐标和结束横坐标。现在有一支笔,要划这些线,这支笔只能从上往下移动,并且只能在x=0的地方从上往下移动。画横线的时候一定要从左到右画,画线移动的时间是普通移动时间的两倍。笔的每次横坐标移动花费时间为1,现在有时间限制t,问最多能画多少条线。
思路:先按y轴、y轴从小到大排序(即我们只能从序号小的移动到序号大的),然后dp[i][j]表示画到第 i 条横线,一共走过了 j 条横线,所花费的最小时间。然后每一个点不同步数找之前的可以走过来的点。暴力点时间复杂度为$O(n^3)$,不过貌似数据比较弱,n≤1000都秒过了。
代码(32MS):
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstring> 5 using namespace std; 6 7 const int MAXN = 1010; 8 9 struct Node { 10 int y, st, ed; 11 void read() { 12 scanf("%d%d%d", &y, &st, &ed); 13 } 14 bool operator < (const Node &rhs) const { 15 if(y != rhs.y) return y < rhs.y; 16 return ed < rhs.ed; 17 } 18 }; 19 20 int length(const Node &a, const Node &b) { 21 if(a.y == b.y) return b.st - a.ed; 22 return a.ed + b.st; 23 } 24 25 Node a[MAXN]; 26 int dp[MAXN][MAXN]; 27 int n, t, ans; 28 29 void solve() { 30 memset(dp, 0x3f, sizeof(dp)); 31 ans = 0; 32 for(int i = 1; i <= n; ++i) { 33 if((dp[i][1] = 2 * a[i].ed - a[i].st) <= t) ans = max(ans, 1); 34 for(int j = 2; j <= i; ++j) { 35 for(int k = j - 1; k < i; ++k) 36 dp[i][j] = min(dp[i][j], dp[k][j - 1] + length(a[k], a[i])); 37 dp[i][j] += 2 * (a[i].ed - a[i].st); 38 if(dp[i][j] <= t) ans = max(ans, j); 39 } 40 } 41 } 42 43 int main() { 44 while(scanf("%d%d", &n, &t) != EOF && n + t) { 45 for(int i = 1; i <= n; ++i) a[i].read(); 46 sort(a + 1, a + n + 1); 47 solve(); 48 printf("%d\n", ans); 49 } 50 }