HNU算法设计与分析(信安)实验三

4-1 会场安排问题

【问题描述】假设要在足够多的会场里安排一批活动,并希望使用尽可能少的会场。设计一个有效的贪心算法进行安排。(这个问题实际上是著名的图着色问题。若将每个活动作为图的一个顶点,不相容活动用边相连。使相邻顶点着有不同颜色的最小着色数,相当于要找的最小会场数。)
【算法设计】对于给定的k个待安排的活动,计算使用最少会场的时间表。
【数据输入】由文件input.txt给出输入数据。第1行有1个正整数k,表示有k个待安排的活动。接下来的k行中,每行有2个正整数,分别表示k个待安排的活动的开始时间和结束时间。时间以0点开始的分钟计。
【结果输出】将计算的最少会场数输出到文件output.txt。

代码如下:

#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>

using namespace std;

int main()
{
    // 打开输入输出文件
    ifstream inFile("input.txt"); // 记得在当前目录创建input.txt并且将数据保存进去
    ofstream outFile("output.txt");

    int n;
    vector<int> s; // 存储活动开始时间
    vector<int> f; // 存储活动结束时间,也即会场空闲时间
    int i,j;
    int ans;

    inFile>>n;
    s.resize(n+1); // 调整vector大小以存储n个活动
    f.resize(n+1);

    for(int i=1;i<=n;i++)
    {
        inFile>>s[i]>>f[i];
    }

    // 按非递减顺序排序开始时间和结束时间
    sort(s.begin()+1, s.end());
    sort(f.begin()+1, f.end());

    j=1; // 初始化:会场最早空闲时间即最早活动结束时间
    ans=1; // 初始化:第一个活动必须分配一个新会场

    // 遍历剩下的活动
    for(int i=2;i<=n;i++)
    {
        // 检查当前最早结束的会场是否可以容纳新的活动
        if (f[j]>s[i])
        {
            ans++; // 需要新开一个会场
        }
        else
        {
            j++; // 当前活动更新为在此会场结束
        }
    }
    outFile<<ans<<endl;

    inFile.close();
    outFile.close();

    return 0;
}
// 运行完成后打开output.txt文件即可看到结果

4-7 多处优服务次序问题

【问题描述】有n个顾客同时等待一项服务。顾客i要的服务时间为ti(1≤i≤n),共有s处可以提供此项服务。应如何安排n个顾客的服务次序,才能使平均等待时间达到最小?平均等待时间是n个顾客等待服务时间的总和除以n。
【算法设计】对于给定的n个顾客需要的服务时间和s的值,计算最优服务次序。
【数据输入】由文件input.txt给出输入数据。第1行有2个正整数n和s,表示有n个顾客且有s处可以提供顾客需要的服务。接下来的1行中有n个正整数,表示n个顾客需要的服务时间。
【结果输出】将计算的最小平均等待时间输出到文件output.txt。

代码如下:

#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

int main(){
    ifstream inputFile("input.txt");
    ofstream outputFile("output.txt");

    int n, s;
    inputFile>>n>>s;

    vector<int> serviceTimes(n);
    for (int i=0;i<n;i++) {
        inputFile>>serviceTimes[i];
    }

    // 按升序排序服务时间以获得最小等待时间
    sort(serviceTimes.begin(),serviceTimes.end());

    // 计算最小平均等待时间
    vector<int> serviceStations(s,0); // 初始化s个服务处,每个服务处的初始时间为0
    long long totalWaitTime=0;

    for(int i=0;i<n;i++){
        // 将当前顾客安排到最早空闲的服务处
        sort(serviceStations.begin(), serviceStations.end());
        totalWaitTime+=serviceStations[0]; // 当前顾客的等待时间等于服务处的完成时间
        serviceStations[0]+=serviceTimes[i]; // 更新服务处的完成时间
    }
    totalWaitTime=totalWaitTime+serviceStations[0]+serviceStations[1]; // 加上等待最后两位的时间

    // 计算平均等待时间
    double averageWaitTime=static_cast<double>(totalWaitTime)/n;

    outputFile<<averageWaitTime<<endl;

    inputFile.close();
    outputFile.close();

    cout<<"计算完成,结果已写入output.txt"<<endl;
    return 0;
}
// 运行完成后打开output.txt文件即可看到结果

4-15 最优分解问题

【问题描述】设n是一个正整数。现在要求将n分解为若干互不相同的自然数的和,且使这些自然数的乘积最大。
【算法设计】对于给定的正整数n,计算最优分解方案。
【数据输入】由文件input.txt提供输入数据。文件的第1行是正整数n。
【结果输出】将计算的最大乘积输出到文件output.txt。

代码如下:

#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

int main(){
    ifstream inputFile("input.txt");
    ofstream outputFile("output.txt");

    int n;
    inputFile>>n;
    inputFile.close();

    long long maxProduct=1;
    // 正整数1~4情况较为特殊,单独处理
    if(n==1){ // 1=0+1
        maxProduct=0;
        outputFile<<maxProduct<<endl;
        outputFile.close();
        return 0;
    }
    if(n==2){ // 2=0+2
        maxProduct=0;
        outputFile<<maxProduct<<endl;
        outputFile.close();
        return 0;
    }
    if(n==3){ // 3=1+2
        maxProduct=2;
        outputFile<<maxProduct<<endl;
        outputFile.close();
        return 0;
    }
    if(n==4){ // 4=1+3
        maxProduct=3;
        outputFile<<maxProduct<<endl;
        outputFile.close();
        return 0;
    }

    vector<int> parts;
    int sum=0;
    int nextNum=2;

    // 不断增加互不相同的自然数,直到总和接近 n
    // 贪心地选择最小的自然数2, 3,...(除1以外),这样保证乘积尽量大
    while(sum+nextNum<=n){
        parts.push_back(nextNum);
        sum+=nextNum;
        nextNum++;
    }

    // 如果总和小于n,将剩余部分均匀地分给前面各项
    int remainder=n-sum;
    int index=parts.size()-1;
    while(remainder>0){
        parts[index]++;
        remainder--;
        index--;
        if(index<0){
            index=parts.size()-1; // 回到最后一个元素,继续均匀分配
        }
    }

    // 计算这些数的乘积
    // 乘积最大化的原因是:分解成接近相等的因子时,乘积达到最大
    for (int num:parts){
        maxProduct*=num;
    }

    outputFile<<maxProduct<<endl;
    outputFile.close();

    cout<<"计算完成,结果已写入output.txt"<<endl;
    return 0;
}

// 运行完成后打开output.txt文件即可看到结果


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值