# POJ 1991 Turning in Homework（由大推小的区间DP）

Turning in Homework
Time Limit: 1000MS Memory Limit: 30000K
Total Submissions: 1172 Accepted: 519
Description

Bessie must turn in her homework for her C classes (1 <= C <= 1,000) at Moo U so that she still has time to chew the cud with her fellow classmates as they wait for the bus to go home.

Teachers accept homework submissions only after they have finished their classes and also cleaned the chalkboard, put away lab supplies,and so on. The input data tells the earliest time a teacher will accept homework.

Bessie starts at one end (distance 0) of a hallway H (1 <= H <= 1,000) meters long and walks at the rate of one meter per second to various classrooms (in any order she chooses) to turn in her homework. Each classroom is located along this hallway, as well as the door to the waiting area for the buses.

Given the location of both the exit and the classrooms and also the teachers’ schedules, determine the earliest time that Bessie can exit the door to the waiting area for the buses. Bessie must turn in all her homework before exiting. The act of turning in the homework takes no time, by the way.
Input

• Line 1: Three integers: C, H, and B. B (0 <= B <= H) is the distance from the hall entrance to the bus waiting area.

• Lines 2..C+1: Each line contains two integers that describe a classroom where homework is to be submitted. The first integer (0..H) is the number of meters to the classroom from the hallway entrance. The second integer (0..10,000) is the first time (in seconds) that the teacher for that course will accept homework.
Output

• Line 1: A single integer: the earliest second that Bessie can exit the door to the waiting area for the buses.
Sample Input

4 10 3
8 9
4 21
3 16
8 12
Sample Output

22
Hint

Time Action

0 Bessie walks to the classrooms 8 meters down the hall (at 8m)

8 Bessie waits 1 second

9 Bessie turns in the first set of homework

9 Bessie waits 3 seconds, thinking about cool hay in the summertime

12 Bessie turns in the other homework for this location

12 Bessie walks back to the classroom 4 meters down the hall (at 4m)

16 Bessie waits 5 seconds, thinking of a handsome bull she once met

21 Bessie turns in her homework

21 Bessie walks back to the classroom 1 meters down the hall (at 3m)

22 Bessie turns in her homework

22 Bessie exits, since this also the location of the bus exit

Thus, Bessie can leave at time 22. No better schedule exists.
Source

USACO 2004 U S Open

### 题目大意

数轴上有一些教室，知道每个教室的位置和开门时间，问从x=0$x=0$的点到所有点交完作业后到达一个给定的终点的最小时间（每个教室只能在开门后才能交作业）。

### 解题思路

首先可以发现当区间[i,j]$[i, j]$的作业都没有交的时候，先访问i$i$或先访问j$j$一定是最优的。
由于最终还要走到一个给定的终点，所以如果按照正常的区间DP，从小区间往大区间推的话就不能考虑到最终位置到终点的距离。所以我们需要反过来从大区间往小区间推。dp[i][j][k]$dp[i][j][k]$表示左端点为i$i$，右端点为j$j$，如果k=0$k=0$则表示除了左端点都没有交现在在左端点，如果k=1$k=1$则表示除了右端点都没有交现在在右端点。那么最终得到dp[i][i][0]=dp[i][i][1]$dp[i][i][0]=dp[i][i][1]$就是交完作业到达i$i$的最短时间，再分别加上到终点的距离找最小值即为答案。
状态的转移就是利用贪心仅在区间的端点转移。总时间复杂度O(N2)$O(N^2)$

### AC代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <cstdlib>
#include <string>
#include <map>
using namespace std;
#define INF 0x3f3f3f3f
#define LL long long
#define fi first
#define se second
#define mem(a,b) memset((a),(b),sizeof(a))
#define sqr(x) ((x)*(x))

const int MAXN=1000+3;
int N, L, T;
pair<int, int> p[MAXN];//位置，解锁时间
int dp[MAXN][MAXN][2];//表示i到j之间除了(k?j:i)都没有交的最小花费

void init()
{
mem(dp, 0x3f);
}

int main()
{
scanf("%d%d%d", &N, &L, &T);
init();
for(int i=1;i<=N;++i)
scanf("%d%d", &p[i].fi, &p[i].se);
sort(p+1, p+1+N);
dp[1][N][0]=max(p[1].fi, p[1].se);
dp[1][N][1]=max(p[N].fi, p[N].se);
for(int len=N-1;len>0;--len)
{
for(int l=1;l+len-1<=N;++l)
{
int r=l+len-1;
if(l>1)
{
dp[l][r][0]=min(dp[l][r][0], dp[l-1][r][0]+p[l].fi-p[l-1].fi);
dp[l][r][1]=min(dp[l][r][1], dp[l-1][r][0]+p[r].fi-p[l-1].fi);
}
if(r<N)
{
dp[l][r][0]=min(dp[l][r][0], dp[l][r+1][1]+p[r+1].fi-p[l].fi);
dp[l][r][1]=min(dp[l][r][1], dp[l][r+1][1]+p[r+1].fi-p[r].fi);
}
//如果需要等待则等待
dp[l][r][0]=max(dp[l][r][0], p[l].se);
dp[l][r][1]=max(dp[l][r][1], p[r].se);
}
}
int ans=INF;
for(int i=1;i<=N;++i)
ans=min(ans, dp[i][i][0]+abs(T-p[i].fi));//加上每个位置到终点的距离更新答案
printf("%d\n", ans);

return 0;
}