黄院--算法实验:贪心算法

此次实验;
题目一:
练习使用贪心算法求解“会场安排”问题;
题目二:
练习使用Prim算法求解“最小生成树”问题。
实验内容:
会场安排问题:假设在足够多的会场里安排一批活动(N个活动),每个活动事先给定活动的开始时间和结束时间,试用贪心算法求出最少需要多少会场,并求出每个活动安排在第几个会场;
例如:5个活动的开始时间和结束时间和会场安排如下

活动12345
开始时间112252736
结束时间2328358050
会场安排

Prim算法求解“最小生成树”问题
在这里插入图片描述
题目一代码:

#include<bits/stdc++.h>
using namespace std;
#define M 100
int array1[M];
int array2[M];
void arange(int array1[M],int array2[M],int n){
    int array3[M];
    memset(array3,0,sizeof(array3));//作用是标记该活动是否已经找到会场。
    int maxnum=0;//需要的会场的个数
    int t=0;//记录当前活动的序号
    int s=0;//每个会场的活动个数
    int counts=0;//记录总共标记的活动数
    while(true){
        s=0;//开始新的一个会场的活动
//        t=0;
        for(int i=0;i<n;i++){
           if(array3[i]==1) continue;//已标记的活动直接跳过
           
               //寻找下一个相容的活动,找到就break
                for(int j=i;j<n;j++){
                     s++;//遍历活动,加一  每个会场的活动个数
                     
               //如果是第一个没归入会场的活动标记下来,归入新会场的第一个活动
                    if(s==1){
                        array3[i]=1;
                        if(t==0){
						printf("活动1加入第%d个会场\n",maxnum+1);
						}
						else
						    printf("活动%d加入第%d个会场\n",t,maxnum+1); 
                        counts++;//已经加入活动的数目加一
                    }

                //得到下一个相容的活动。,归入新的会场,结束循环
                if(array2[i]<array1[j] && array3[j]==0){
                    array3[j]=1;
                    t=j;//更新归入的活动的坐标,下次从这个活动向后找
					printf("第%d个活动安排在第%d个会场\n",t+1,maxnum+1);
                    counts++;//已经加入会场的数目加一
                    break;
                }
                }
        }
        maxnum++;//会场的数目加一
        if(counts==n){//所有活动处理完,结束
            break;
        }
    }
    cout << "需要会场数:"; 
    cout << maxnum;
}
int main()
{
    int n;
    cout<< "请输入会场个数:\n"; 
    cin >> n;
    printf("起点时间   终止时间\n");
    memset(array1,0,sizeof(array1));//用户输入的活动的起始点
    memset(array2,0,sizeof(array2));//用户输入的活动的结束时间
    for(int i=0;i<n;i++){
        cin >> array1[i] >> array2[i];
    }
    int array3[n];
    int array4[n];
    memset(array3,0,sizeof(array3));//存储排序后的活动的起始点
    memset(array4,0,sizeof(array4));//存储排序后的活动的终止时间点
     for(int i=0;i<n;i++){//复制一下起始时间,
        array3[i]=array1[i];
    }
    sort(array3,array3+n);//所有的活动根据起始时间进行排序用array3和array4进行存储
      for(int i=0;i<n;i++){
        for(int j=0;j<n;j++)
        {
            if(array1[j]==array3[i]){
                array4[i]=array2[j];
            }
        }
    }
      arange(array3,array4,n);
}

在这里插入图片描述
嘿嘿~代码还是有毛病,不过我也懒得改了就这样了吧。。。
题目二代码:

#include<stdio.h>
#include <stdlib.h>
#define MAX 100
#define Maxcost 0x7fffffff
int graph[MAX][MAX];
void prim(int graph[][MAX],int n){
    int i,j,k;
    int lowcost[MAX];
    int closeset[MAX],used[MAX];
    int mmin;
    int sumcost=0;
    printf("最小生成树的边为:\n");
    for(i=1;i<=n;i++){
        lowcost[i]=graph[1][i];
        //printf("lowcost[%d]=%d\n",i,lowcost[i]);
        closeset[i]=1;
        used[i]=0;
    }
    used[1]=1;
    for(i=2;i<=n;i++){
        j=1;
        mmin=Maxcost;
        for(k=2;k<=n;k++){
            if((!used[k])&&(lowcost[k]<mmin)){
                mmin=lowcost[k];
                j=k;
            }
        }
        printf("%d %d\n",j,closeset[j]);
        sumcost+=graph[j][closeset[j]];
        used[j]=1;
        for(k=2;k<=n;k++){
            if(!used[k]&&(graph[j][k]<lowcost[k])){
                lowcost[k]=graph[j][k];
                closeset[k]=j;
            }
            //printf("lowcost[%d]=%d\n",k,lowcost[k]);
        }
    }
    printf("最小造价为:%d\n",sumcost);
}
int main(){
    FILE *fr;
    int s,e;
    int i,j,weight;
    fr=fopen("input.txt","r");
    if(!fr){
        printf("openning file failed!\n");
        exit(1);
    }
    fscanf(fr,"%d %d",&s,&e);
    printf("共%d个点 %d条边\n",s,e);
    for(i=0; i<=e; i++)
    for(j=0; j<=e; j++)
        graph[i][j] = Maxcost;
    while(e--){
        fscanf(fr,"%d%d%d",&i,&j,&weight);
        printf("%d %d %d\n",i,j,weight);
        graph[i][j]=weight;
        graph[j][i]=weight;
    }
    prim(graph,s);
    return 0;
}

输入数据的txt文件内容:
在这里插入图片描述
运行结果图;
在这里插入图片描述
完啦~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值