GIS算法基础丨第一周作业

问题1:最佳工作序列

有N件工作,输入每件工作的费时、最后完成的期限以及工作的价值,试求可能的一个完成工作序列,使得价值和最大。

/*
* GIS算法第一周作业 luo
* 
* 程序功能:有N件工作,输入每件工作的费时、最后完成期限以及工作的价值,
* 试求可能的一个完成工作序列,使价值之和最大。
* 
* luo 2024/9/2 最佳工作序列
* 存在问题:代码样例限制了每件工作费时1天
* 
* luo 2024/9/3 修改程序使得程序需要考虑每件工作所花费的时间
* 存在问题:从最后期限开始安排工作使得前面有些天数并没有安排工作,而原先排在后面但能够完成得工作无法参与排序
* 改进方法:增加一个否有时间间隙的判断,若间隙之和能够安排下工作,则可以将已经安排好的工作提前
* 
* luo 2024/9/4 修改程序改进了昨天存在的问题
*  
*/

#define _CRT_SECURE_NO_WARNINGS  
#include <stdio.h>  
#include <stdlib.h>  
#include <stdbool.h>  

#define MAX_DAYS 50 // 最大累积工作时长  

typedef struct
{
    char id;      // 工作代号  
    int duration; // 费时  
    int deadline; // 最后期限   
    int value;    // 价值  
} Job;

void profitSort(Job* jobs, int n);            // 用于工作收益效率的降序排序
int findMaxDDL(Job* jobs, int n);             // 用于寻找最晚期限
void printResult(char result[], bool slot[], int n); // 用于打印最佳工作序列结果
void findBestJobScheduling(Job* jobs, int n); // 用于寻找最佳工作序列的函数  

int main()
{
    int n;
    printf("请输入工作数量: ");
    if (scanf("%d", &n) != 1 || n <= 0) 
    {
        printf("输入无效,请输入一个正整数。\n");
        return 1;
    }

    Job* jobs = (Job*)malloc(n * sizeof(Job));
    if (jobs == NULL)
    {
        printf("内存分配失败。\n");
        return 1;
    }

    for (int i = 0; i < n; i++)
    {
        printf("请输入第%d个工作的代号、费时、最后期限以及价值:\n", i + 1);
        if (scanf(" %c %d %d %d", &jobs[i].id, &jobs[i].duration, &jobs[i].deadline, &jobs[i].value) != 4)
        {
            printf("输入格式错误。\n");
            free(jobs);
            return 1;
        }
    }

    findBestJobScheduling(jobs, n);

    free(jobs);

    return 0;
}

void profitSort(Job* jobs, int n)
{
    for (int i = 0; i < n - 1; i++)
    {
        for (int j = 0; j < n - 1 - i; j++)
        {
            double profitA = (double)jobs[j].value / jobs[j].deadline;
            double profitB = (double)jobs[j + 1].value / jobs[j + 1].deadline;
            if (profitA < profitB)
            {
                Job temp = jobs[j];
                jobs[j] = jobs[j + 1];
                jobs[j + 1] = temp;
            }
        }
    }
}

int findMaxDDL(Job* jobs, int n)
{
    int maxDDL=jobs[0].deadline;
    for (int i = 1; i < n; i++)
    {
        if (jobs[i].deadline > maxDDL)
        {
            maxDDL = jobs[i].deadline;
        }
    }
    return maxDDL;
}

void printResult(char result[], bool slot[], int n)
{
    printf("最佳工作序列为:");
    for (int i = 0; i < n; i++)
    {
        if (result[i] != result[i + 1] || result[i + 1] == 0)
        {
            printf("%c ", result[i]);
        }
    }
}

void findBestJobScheduling(Job* jobs, int n)
{
    // 1、按工作的profit进行升序排序(冒泡排序)
    profitSort(jobs, n);

    // 2、找到最晚期限
    int max_DDL = findMaxDDL(jobs, n);
    char result[MAX_DAYS] = { 0 };     // 用于存储工作序列结果  
    bool slot[MAX_DAYS] = { false };   // 用于标记特定日期是否有工作安排
    int value_sum = 0;                 // 用于记录最终的价值之和


    // 3、寻找最佳工作序列   
    for (int i = 0; i < n; i++)
    {
        int record = 0;     //计算第i个工作最后期限前有多少天为空
        for (int j = jobs[i].deadline - 1; j >= 0 && slot[j] == false; j--)
        {
            record++;
        }

        if (record >= jobs[i].duration)  // 若空出的天数足够用于安排工作
        {
            for (int k = jobs[i].deadline - 1; k >= jobs[i].deadline - jobs[i].duration; k--)
            {
                result[k] = jobs[i].id;
                slot[k] = true;
            }
            value_sum += jobs[i].value;
        }

        else                             // 若当前期限前空出天数无法安排工作
        {
            //记录ddl前空余的天数
            int valible_days = 0;
            for (int k = 0; k <jobs[i].deadline; k++)
            {
                if (slot[k] == false)
                {
                    valible_days++;
                }
            }

            if (valible_days >= jobs[i].duration)  // 若空余天数能安排下该工作  
            {
                int daysMoved = 0;
                // 将之前安排的工作提前  
                for (int k = 0; k < jobs[i].deadline; k++)
                {
                    while(slot[k] == false && daysMoved < jobs[i].duration)  // 若当前时间空余则将之后的工作往前
                    {
                        for (int pos = k; pos < jobs[i].deadline; pos++)
                        {
                            result[pos] = result[pos + 1];
                            slot[pos] = slot[pos + 1];
                        }
                        daysMoved++;
                    }
                }

                //将新的工作安排在ddl之前
                for (int k = jobs[i].deadline - 1; k >= jobs[i].deadline - jobs[i].duration; k--)
                {
                    result[k] = jobs[i].id;
                    slot[k] = true;
                }
                value_sum += jobs[i].value;
            }
        }
    }

    // 4、输出结果  
    printf("\n");
    printResult(result, slot, max_DDL);
    printf("\n");
    printf("最终价值总和为%d", value_sum);
    
}

问题2:最长路径问题

现有一个nxn大小的格网,其中有些格子无法走通,已知出发点为(0,0),问在这个格网中从起点开始直到边界走过的最长路径(格子数)为多少?
要求:
①不能走回头路,格子不重复
②前进方向为上、下、左、右,不能斜着走

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值