【编程素质】活动安排问题(会场安排问题、图着色问题)

贪心算法

1,问题

活动时间表
i-第i个活动
s[i]:开始时间。
f[i]:结束时间。
贪心算法:
选择活动1,则开始时间大于4的最近活动为:活动4。
选择活动4,开始时间大于7的最近活动为:活动8。
选择活动8,同样,选择活动11。

2,demo

1)会场安排问题。

【问题描述】假设要在足够多的会场里安排一批活动,并希望使用尽可能少的会场。(这个问题实际上是著名的图着色问题。若将每一个活动作为图的一个顶点,不相容活动间用边相连。使相邻顶点有不同颜色的最小着色数,相应于要找的最小会场数。)
【算法设计】对于给定的K个待安排活动,计算使用最少会场的时间表

2)代码

①C语言实现

input.txt

5
1 23
12 28
25 35
27 80
36 50

output.txt

//要求每个活动安排完,记录使用会场的最少数
#include <stdio.h>
#include <stdlib.h>

typedef struct
{
    int s;//记录活动开始时间
    int f;//记录活动终止时间
    int A;//活动是否被安排
}Activity;

void SelectSort( Activity a[],int n );
int GreedySelector( int n, Activity a[] );

int main()
{
    int n;//记录有几项活动
    int count=0;//记录会场数
    int i = 0;
    Activity a[100];

    FILE *fp1,*fp2;
    fp1 = fopen("C:\\Users\\LUO\\Desktop\\input.txt","r");
    fp2 = fopen("C:\\Users\\LUO\\Desktop\\output.txt","a");
    if(!fp1)
    {
        printf("open fp1 failed!");
    }
    fscanf(fp1,"%d\n",&n);
    while( !feof(fp1) )
    {
        fscanf(fp1,"%d%d", &a[i].s ,&a[i].f);
        i++;
    }
    for( i=0; i<n; i++ )
        a[i].A = 0;

    SelectSort(a,n);//按活动结束时间从小到大排列
    count = GreedySelector( n,a );

    fprintf(fp2,"%d\n",count);
    fclose( fp1 );
    fclose( fp2 );

    return 0;
}

void SelectSort( Activity a[],int n )
{//从小到大排列
    int i,j,k;
    Activity temp;
    for( i=0; i<n; i++ )
    {
        k = i;
        for( j=i+1; j<n; j++ )
            if( a[j].f < a[k].f )
                k = j;
        if( i != k )
        {
            temp = a[i];
            a[i] = a[k];
            a[k] = temp;
        }
    }
}

int ifAll(Activity a[],int n)
{
   int i;
   for( i=0; i<n; i++ )
   {
        if( a[i].A == 0 )
            return 0;
   }
   return 1;
}

int GreedySelector( int n, Activity a[] )
{
    int i;
    int j;//已选的会场
    int count;//会场计数

    for( count=1; !ifAll(a,n); count++)
    {
        for( i=0; i<n; i++ )
        {
            if( !a[i].A )
            {
                j=i;
                a[i].A = 1;
                break;
            }
        }
        for( i=0; i<n; i++ )
        {
            if( !a[i].A )
                if( a[i].s >= a[j].f )//
                {
                    a[i].A = 1;
                    j=i;
                }
        }
    }
    return --count;
}

②java实现

input.txt

5,
1,23,
12,28,
25,35,
27,80,
36,50,
package task_scheduling;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class Main1 {

    private static int SIZE = 15;// 数组大小

    public static void main(String[] args) throws IOException {

        int n;// 记录有几项活动
        int count = 0;// 记录会场数
        MovementBean[] m = new MovementBean[SIZE];
        for (int i = 0; i < m.length; i++) {
            m[i] = new MovementBean(0, 0, false);
        }

        int[] data = ReadFile();
        n = data[0];
        for (int i = 1, j = 0; i < data.length; j++) {
            m[j].setStartTime(data[i++]);
            m[j].setFinalTime(data[i++]);
            m[j].setSelect(false);
        }

        SelectSort(m, n);// 按活动结束时间从小到大排列
        count = GreedySelector.GreedySelector(n, m);

        if (0 == count) {
            System.out.println("计算出错");
        } else {

            // out.txt
            FileUtil.writeFile("output.txt", count + "");
        }
    }

    private static void SelectSort(MovementBean[] m, int n) {// 从小到大排列
        int i, j, k;
        MovementBean temp;
        for (i = 0; i < n; i++) {
            k = i;
            for (j = i + 1; j < n; j++)
                if (m[j].getFinalTime() < m[k].getFinalTime())
                    k = j;
            if (i != k) {
                temp = m[i];
                m[i] = m[k];
                m[k] = temp;
            }
        }
    }

    /**
     * Read input.txt
     * 
     * @throws IOException
     */
    private static int[] ReadFile() throws IOException {

        int[] Data = new int[SIZE];// 文件读取到的数据转换为int存储
        String[] Data_str = new String[SIZE];// 文件读取到的数据

        Data_str = FileUtil.readFile("input.txt").split("\\,");

        int index = 0;
        for (String item : Data_str) {

            Data[index++] = Integer.parseInt(item);
        }
        return Data;
    }
}
package task_scheduling;
/**
 * 活动类
 * @author luo
 *
 */
public class MovementBean {

    private int startTime;//记录活动开始时间
    private int finalTime;//记录活动终止时间
    private boolean isSelect;//活动是否被安排
    public MovementBean(int s, int f, boolean isSelect){
        this.startTime = s;
        this.finalTime = f;
        this.isSelect = isSelect;
    }
    public int getStartTime() {
        return startTime;
    }
    public void setStartTime(int startTime) {
        this.startTime = startTime;
    }
    public int getFinalTime() {
        return finalTime;
    }
    public void setFinalTime(int finalTime) {
        this.finalTime = finalTime;
    }
    public boolean isSelect() {
        return isSelect;
    }
    public void setSelect(boolean isSelect) {
        this.isSelect = isSelect;
    }
}

核心代码:

package task_scheduling;

/**
 * 会场安排问题
 * 
 * @author luo
 *
 */
public class GreedySelector {

    public static int GreedySelector(int n, MovementBean m[]) {
        int i;
        int j = 0;// 已选的会场
        int count;// 会场计数

        for (count = 1; !ifAll(m, n); count++) {
            for (i = 0; i < n; i++) {
                if (!m[i].isSelect()) {
                    j = i;
                    m[i].setSelect(true);
                    break;
                }
            }
            for (i = 0; i < n; i++) {
                if (!m[i].isSelect())
                    if (m[i].getStartTime() >= m[j].getFinalTime())//
                    {
                        m[i].setSelect(true);
                        j = i;
                    }
            }
        }
        return --count;
    }

    /**
     * 判断任务是否全部被选中
     * 
     * @param m
     * @param n
     * @return
     */
    private static boolean ifAll(MovementBean m[], int n) {
        int i;
        for (i = 0; i < n; i++) {
            if (!m[i].isSelect())
                return false;
        }
        return true;
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值