[pta]5-5求解活动安排问题(回溯法)

假设有一个需要使用某一资源的n个活动所组成的集合S,S={1,…,n}。该资源任何时刻只能被一个活动所占用,活动i有一个开始时间bi和结束时间ei(bi<ei),其执行时间为ei-bi,假设最早活动执行时间为0。
一旦某个活动开始执行,中间不能被打断,直到其执行完毕。若活动i和活动j有bi≥ej或bj≥ei,则称这两个活动兼容。
设计算法求一种最优活动安排方案,使得所有安排的活动个数最多。

输入格式:

第一行是一个整数n,接着的n行中每一行包括两个整数b和e,其中b是一个订单开始时间,e是的结束时间。。

输出格式:

若count表示最大兼容活动集合数,先输出count行,每行为活动的开始时间和结束时间。最后输出count。

输入样例1:

4
1 3
2 5
4 8
6 10

输出样例1:

[1,3)
[4,8)
2 

代码:

#include <stdio.h>
#include <string.h>
#include <iostream>
#define MAX 51
using namespace std;
//问题表示
struct Action
{
    int b;                    //活动起始时间
    int e;                    //活动结束时间
};
int n=4;
Action A[MAX]={{0,0}};        //下标0不用
//求解结果表示
int x[MAX];                    //解向量
int bestx[MAX];                //最优解向量
int laste=0;                //一个方案中最后兼容活动的结束时间
int sum=0;                    //一个方案中所有兼容活动个数
int maxsum=0;                //最优方案中所有兼容活动个数

void swap(int &x,int &y)    //交换x、y
{    int tmp=x;    x=y; y=tmp;}

void dispasolution()                    //输出一个解
{
    int laste=0;
    for (int j=1;j<=n;j++)
    {
        if (A[bestx[j]].b>=laste)        //选取活动bestx[j]
        {
            printf("[%d,%d)\n",A[bestx[j]].b,A[bestx[j]].e);
            laste=A[bestx[j]].e;
        }
    }
    printf("%d",maxsum);
}

void action(int i)                            
{
    if (i>n)                
    {
        if (sum>maxsum)
        {
            maxsum = sum;
            for (int k=1;k<=n;k++)
                bestx[k] = x[k];
        }
    }
    else
    {
        for(int j=i; j<=n; j++)                
        {    
            int sum1=sum;            
            int laste1=laste;
            if (A[x[j]].b>=laste)        
            {
                laste = A[x[j]].e;                
                sum++;        
            }
            swap(x[i],x[j]);                
            action(i+1);                
            swap(x[i],x[j]);    
            sum=sum1;        
            laste=laste1;                    
        }
    }
}

int main()
{
    cin>>n;
    for (int i=1;i<=n;i++)
       cin>>A[i].b>>A[i].e;    
    for (int i=1;i<=n;i++)
        x[i]=i;
        action(1);                                //i从1开始搜索
    dispasolution();                    //输出结果
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值