poj 1991 Turning in Homework(贪心+区间dp)

题目链接:poj 1991 Turning in Homework

题意:

Bessie要交作业,现在知道每个教师的位置,假设都位于X轴上,每份作业都有一个最早交的时间,知道公交车站位于坐标B的对面,假设他每走一个单位耗费时间是1,求他交完作业到达公交车站那最少的时间是什么?

题解:

思想比较好,下面题解来自网上:

贪心:当有一段连续区间[i,j]未交时,取i或j是最优的。

贪心思想证明:如果在[i,j]这段连续区间都没有被取的时候取了中间的m,那么后来一定要从m返回到i或者j,这时候是一定走了“冤枉路的”。而如果这时取了i或者j,那么到中间的时候m一定可以取。证毕。

区间DP:

dp[i][j][0]表示为i-j区间尚未完成交作业的最少时间,其中0代表只交了i作业,dp[i][j][1]同理就是只交了j作业,那么我们将很容易想出来,这是由大区间逐渐推出小区间的一个过程,最终的dp[i][i][0]和dp[i][i][1]就代表停留在i位置的最少时间,最后再加上i-B的距离就是到达公交车站的时间

状态转移方程有四个

 dp[i][j][0]=min(dp[i][j][0],dp[i-1][j][0]+c[i].x-c[i-1].x);

 dp[i][j][0]=min(dp[i][j][0],dp[i][j+1][1]+c[j+1].x-c[i].x);

  dp[i][j][1]=min(dp[i]j][1],dp[i-1][j][0]+c[j].x-c[i-1].x);

 dp[i][j][1]=min(dp[i][j][1],dp[i][j+1][1]+c[j+1].x-c[j].x);

每次还有和时间比较下,有可能走到那个点了,却还不够最早交作业的时间。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define F(i,a,b) for(int i=a;i<=b;++i)
 4 using namespace std;
 5 typedef pair<int,int>P;
 6 
 7 const int N=1007,inf=1e9+7;
 8 
 9 int n,h,b,dp[N][N][2];
10 P a[N];
11 
12 void up(int &a,int b){if(a>b)a=b;}
13 
14 int main(){
15     while(~scanf("%d%d%d",&n,&h,&b))
16     {
17         F(i,0,n+1)F(j,0,n+1)dp[i][j][0]=dp[i][j][1]=inf;
18         F(i,1,n)scanf("%d%d",&a[i].first,&a[i].second);
19         sort(a+1,a+1+n);
20         dp[1][n][0]=max(a[1].first,a[1].second);
21         dp[1][n][1]=max(a[n].first,a[n].second);
22         F(i,1,n)for(int j=n;j>=i;j--)
23         {
24             up(dp[i][j][0],max(dp[i-1][j][0]+a[i].first-a[i-1].first,a[i].second));
25             up(dp[i][j][0],max(dp[i][j+1][1]+a[j+1].first-a[i].first,a[i].second));
26             up(dp[i][j][1],max(dp[i-1][j][0]+a[j].first-a[i-1].first,a[j].second));    
27             up(dp[i][j][1],max(dp[i][j+1][1]+a[j+1].first-a[j].first,a[j].second));
28         }
29         int ans=inf;
30         F(i,1,n)up(ans,min(dp[i][i][0],dp[i][i][1])+abs(a[i].first-b));
31         printf("%d
",ans);
32     }
33     return 0;
34 }
View Code
原文地址:https://www.cnblogs.com/bin-gege/p/7658556.html