【动态规划dp】火车进站(train)

火车进站(train)

【题目描述】

火车站内往往设有一些主干线分叉出去的铁路支路,供火车停靠,以便上下客或装载货物。铁路
支路有一定长度;火车也有一定的长度,且每列火车的长度相等。
假设某东西向的铁路上,有一小站。该站只有一条铁路支路可供火车停靠,并且该铁路支路最多
能容纳 M 辆火车。为了火车行驶的通畅,该站只允许火车自东方进站,自西方出站,且先进站的火车
必须先出站,否则,站内火车将发生堵塞。
该火车站工作任务繁忙。每天都有 N 辆自东方驶向西方的火车要求在预定时刻进站,并在站内作
一定时间的停靠。为了满足每辆进站火车的要求,小站的调度工作是井井有条地开展。在小站每天的
工作开始前,小站工作人员须阅读所有火车的进站申请,并决定究竞接受哪些火车的申请。而对于不能
满足要求的火车,小站必须提前通知它们,请它们改变行车路线,以免影响正常的铁路运输工作。由
于火车进站、出站的用时可以忽略不计,小站允许几辆火车同时进站或出站,且小站工作人员可以任
意安排这些火车进站的先后排列次序。小站的工作原则是尽量地满足申请火车的要求。
请你编一个程序,帮助工作人员考察某天所有火车的进站申请,计算最多能满足多少火车的要求。

【输入格式】

共 N+1 行。
第一行是两个正整数 N 和 M。(N<=100, M<=3);
以下 N 行每行是一辆火车的进站申请,第 i+1 行的两个整数分别表示第 i 列火车的进站的时间和
火车出站的时间。

【输出格式】

仅一行,是一个正整数 B,表示火车站最多能接纳的火车数量。

【输入样例】

6 3
2 4
1 7
3 6
5 7
8 10
9 11

【输出样例】

5

————————————————————分割の线————————————————————

既然m只有3,那就分为3类来做。

先将申请排序,进站时刻为第一关键字,出站第二。
设r[i].f & r[i].e分别为第i辆火车的进站和出站时间。

m=1时,如果要同时接受i、j两辆车,就要满足

    r[i].e<=r[j].f
    那么f[i]为接受第i辆车时已接受的最大车数。

f[i]=max(f[j])+1;初始f[1]=1,其他为0;枚举j=1 to i-1就好了。

        r[i].e<=r[k].f,r[i].e<r[j].e.
        同样的,g[i][j]为接受i、j两辆车时已接受的最大火车数。

g[i][j]=max(g[k][i]+1);初始全为2;枚举k=1 to i-1.
m=3时,如果接受i、j、k,以及l辆车

r[i].tt<=r[j].tt && r[j].tt<=r[k].tt&&r[l].tt<=r[k].t

h[i][j][k]=max(h[l][i][j]+1);初始全为3;枚举l=1 to i-1.

最后的答案是取f数组中的最大值。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct node
{
    int f,e;
}r[110];
int f[110],g[110][110],h[110][110][110];

int cmp(node x,node y)
{
    if(x.f==y.f) return x.e<y.e;
    return x.f<y.f;
}
int main()
{
    freopen("train.in","r",stdin);
    freopen("train.out","w",stdout);
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        scanf("%d%d",&r[i].f,&r[i].e);
    sort(r+1,r+n+1,cmp);
    if(m==1)
    {
        memset(f,0,sizeof(f));
        f[1]=1;
        for(int i=2;i<=n;i++)
            for(int j=1;j<i;j++)
                if(r[j].e<=r[i].f) f[i]=max(f[i],f[j]+1);
        int ans=0;
        for(int i=1;i<=n;i++)
            if(f[i]>ans)ans=f[i];
        cout<<ans<<endl;
    }
    if(m==2)
    {
        int ans=0;
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
            {
                if(r[i].e>r[j].e)continue;
                g[i][j]=2;
                for(int k=1;k<i;k++)
                    if(r[k].e<=r[j].f)
                        g[i][j]=max(g[i][j],g[k][i]+1);
                if(g[i][j]>ans)ans=g[i][j];
            }
        cout<<ans<<endl;
    }
    if(m==3)
    {
        int ans=0;
        for(int i=1;i<=n;i++)
            for (int j=i+1;j<=n;j++)
                for (int k=j+1;k<=n;k++)
                    if(r[i].e<=r[j].e && r[j].e<=r[k].e)
                    {
                        h[i][j][k]=3;
                        for (int l=1;l<i;l++)
                            if (r[l].e<=r[k].f)
                                h[i][j][k]=max(h[l][i][j]+1,h[i][j][k]);
                        ans=max(h[i][j][k],ans);
                    }
        cout<<ans<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一列货运列车共有 n 节车厢,每节车厢将停放在不同的车站。假定 n 个车站的编号分别 为 1~n,车厢的编号与它们的目的地相同。货运列车按照从第 n 站至第 1 站的次序经过这 些车站。为了便于从列车上卸掉相应的车厢,必须重新排列车厢,使各车厢从前至后按编号 1~n 的次序排列。当所有的车厢按照这种次序排列时,在每个车站只卸掉最后一节车厢 即可。可以在一个转轨站里完成车厢的重排工作,在转轨站中有一个入轨,一个出轨和k 个缓冲铁轨(位于入轨和出轨之间)。 图 3-1 给出了一个转轨站, 其中有 k=3 个缓冲铁轨 H1,H2 和 H3。开始时,n节车厢的货车从入轨处进入转轨站,车厢重排结束时各车厢按照编号1至编号n的次序从出轨处离开转轨站。在图 3-1(a)中,n=9,车厢从后至前的初始次序为 5,8,1,7,4,2,9,6,3。图 3-1(b)给出按所要求的次序重新排列后的结果。 为了重排车厢,从前至后依次检查入轨上的所有车厢。如果正在检查的车厢就是下一个满足排列的要求的车厢,可以直接把它放到出轨上。如果不是,则把它移动到缓冲铁轨上, 直到按输出次序要求轮到它时才将它放到出轨上。由于缓冲铁轨上车厢的进和出都是在其顶 部进行的,因此缓冲铁轨是按照 LIFO 的方式使用的。在重排车厢过程中,仅允许以下移动:  车厢可以从入轨移动到一个缓冲铁轨的顶部或者出轨上;  车厢可以从一个缓冲铁轨的顶部移动到的出轨上;

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值