【动规递推】最优时间表 sche

最优时间表
sche.pas/cpp)

 

【问题描述】

一台精密仪器的工作时间为 n 个时间单位。与仪器工作时间同步进行若干仪器维修程序。一旦启动维修程序,仪器必须进入维修程序。如果只有一个维修程序启动,则必须进入该维修程序。如果在同一时刻有多个维修程序,可任选进入其中的一个维修程序。维修程序必须从头开始,不能从中间插入。一个维修程序从第s个时间单位开始,持续t个时间单位,则该维修程序在第s+t-1个时间单位结束。为了提高仪器使用率,希望安排尽可能少的维修时间。

   编程任务:对于给定的维修程序时间表,编程计算最优时间表。

 

【输入数据】

第 1 行有2 个正整数n和 k(1≤n,k≤9999)。n表示仪器的工作时间单位;k是维修程序数。接下来的k行中,每行有2 个表示维修程序的整数s和 t,该维修程序从第s个时间单位开始,持续t个时间单位。

 

【输出数据】

最少维修时间。

 

【样例输入】sche.in

15 6

1 2

1 6

4 11

8 5

8 1

11 5

 

【样例输出】sche.out

11

 

 

这一题用搜索应该能做,不过效率很低,当时没做出来

用动规的话可以换一种思维求最大工作时间

正序枚举的话就会面临题目中所说的只有一个必须取,多个随便取一个,很不好判断,所以可以逆序枚举

用f[i]表示 i~n 的最大工作时间,如果没有以 i 为开头的维修工作,那么f[i]=f[i+1]+1(这里的1是由于没有维修任务,就尽可能的多工作,所以加一个时间单位)
如果有,就从里面选一个最大值f[i]=max{f[i+tj]}

最后输出答案用n减去f[1]即可

 

C++ Code

 

/*
C++ Code
http://oijzh.cnblogs.com
*/
#include<cstdio>
#include<string>
#include<list>
using namespace std;
#define MAXN 10010
#define oo 999999999

int n,k,f[MAXN];
struct tnode{int t;tnode* next;};
tnode* first[MAXN];

void insert(int s,int t)
{
    tnode*aa=new tnode;
    aa->t=t;
    aa->next=first[s];
    first[s]=aa;
}

int main()
{
    freopen("sche.in","r",stdin);
    freopen("sche.out","w",stdout);
    scanf("%d%d",&n,&k);
    int i,j,s,t;
    for(i=1;i<=k;i++)
    {
        scanf("%d%d",&s,&t);
        insert(s,t);
    }
    for(i=n;i>=1;i--)
    {
        if(!first[i]){f[i]=f[i+1]+1;}
        tnode* node=first[i];
        while(node)
        {
            f[i]=max(f[i],f[i+node->t]);
            node=node -> next;
        }
    }
    printf("%d",n-f[1]);
    return 0;
}

 

 

 

还有一种方法就是直接推最短维修时间,不过要赋初值,其他改动的就是f[i]取min,最后输出f[1]

#include<cstdio>
#include<string>
#include<list>
using namespace std;
#define MAXN 10010
#define oo 999999999

int n,k,f[MAXN];
struct tnode{int t;tnode* next;};
tnode* first[MAXN];

void insert(int s,int t)
{
    tnode*aa=new tnode;
    aa->t=t;
    aa->next=first[s];
    first[s]=aa;
}

int main()
{
    freopen("sche.in","r",stdin);
    freopen("sche.out","w",stdout);
    scanf("%d%d",&n,&k);
    int i,j,s,t;
    for(i=1;i<=k;i++)
    {
        scanf("%d%d",&s,&t);
        insert(s,t);
    }
    memset(f,63,sizeof(f));
    f[n+1]=n;
    for(i=n;i>=1;i--)
    {
        if(!first[i]){f[i]=f[i+1]-1;}
        tnode* node=first[i];
        while(node)
        {
            f[i]=min(f[i],f[i+node->t]);
            node=node -> next;
        }
    }
    printf("%d",f[1]);
    return 0;
}

 

转载于:https://www.cnblogs.com/oijzh/archive/2012/09/19/2694361.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值