实验三—贪心算法

贪心算法实验(第三次)

会场安排问题

问题描述:

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

编程任务:

对于给定的k 个待安排的活动,编程计算使用最少会场的时间表。

数据输入:

由文件input.txt 给出输入数据。第一行有1 个正整数k,表示有k 个待安排的活动。接下来的k 行中,每行有2 个正整数,分别表示k 个待安排的活动开始时间和结束时间。时间以0 点开始的分钟计。

结果输出:

将编程计算出的最少会场数输出到文件output.txt 。

输入文件示例输出文件示例

input.txt output.txt

5 3

1 23

12 28

25 35

27 80

36 50

#include<iostream>
using namespace std;

struct ans{
    int begin,end;
    bool flag ;
};

int func(int k,ans *a)
{
    int ct = k, r_a=0, r_n=0;
    while(ct>0)
    {
        for(int i=1;i<=k;i++)
        {
            if((a[i].begin>r_a) && (a[i].flag==0))
            {
                r_a = a[i].end;
                a[i].flag=1;
                ct--;
            }
        }
        r_a=0;
        r_n++;
    }
    return r_n;
}
int main()
{
    int k,r_n;
    cin>>k;
    ans a[k+1];
    for(int i=1;i<=k;i++)
    {
        cin>>a[i].begin>>a[i].end;
        a[i].flag=0;
    }
    r_n=func(k, a);
    cout<<r_n<<endl;
    return 0;
}

硬币找钱问题

问题描述:

设有6 种不同面值的硬币,各硬币的面值分别为5 分,1 角,2 角,5 角,1 元,2 元。现要用这些面值的硬币来购物和找钱。购物时可以使用的各种面值的硬币个数存于数组Coins[1:6 ]中,商店里各面值的硬币有足够多。在1 次购物中希望使用最少硬币个数。

例如,1 次购物需要付款0.55 元,没有5 角的硬币,只好用2*20+10+5 共4 枚硬币来付款。如果付出1 元,找回4 角5 分,同样需要4 枚硬币。但是如果付出1.05 元(1 枚1 元和1 枚5 分),找回5 角,只需要3 枚硬币。这个方案用的硬币个数最少。

编程任务:

对于给定的各种面值的硬币个数和付款金额,编程计算使用硬币个数最少的交易方案。

数据输入:

由文件input.txt 给出输入数据。每一行有6 个整数和1 个有2 位小数的实数。分别表示

可以使用的各种面值的硬币个数和付款金额。文件以6 个0 结束。

结果输出:

将编程计算出的最少硬币个数输出到文件output.txt 。结果应分行输出,每行一个数据。如果不可能完成交易,则输出”impossible”。

输入文件示例

input.txt

2 4 2 2 1 0 0.95

2 4 2 0 1 0 0.55

0 0 0 0 0 0

输出文件示例

output.txt

2

3

#include <iostream>
#include <cstring>
using namespace std;

const int N = 20000;
int change[N];
int dp[N];
int value[6] = { 1,2,4,10,20,40 };
int number[10];

void init() {
	int i, j;
	for (i = 0; i < N; i++)change[i] = -1;
	change[0] = 0;
	for (i = 0; i < 6; i++) {
		for (j = value[i]; j < N; j++) {
			if (change[j - value[i]] != -1) {
				int tmp = change[j - value[i]] + 1;
				if (change[j] == -1 || tmp < change[j])change[j] = tmp;
			}
		}
	}
}



int main(void) {

	init();
	while (1) {
		int flag = 0;
		for (int i = 0; i < 6; i++) {
			cin >> number[i];
			if (number[i] != 0) {
				flag = 1;
			}
		}
		if (flag == 0) {
			break;
		}
		int sum = 0;
		int kk;
		for (kk = 0; kk < 6; kk++)sum += number[kk];
		if (sum == 0)break;
		double weight;
		cin >> weight;
		weight = weight * 100;
		int w = int(weight + 0.0000001);
		if (w % 5 != 0) {
			printf("impossible\n");
			continue;
		}
		else {
			w = w / 5;
			int i, j;
			memset(dp, -1, sizeof(dp));
			dp[0] = 0;
			int bigger = 0;
			for (i = 0; i < 6; i++) {
				while (number[i]--) {
					bigger = bigger + value[i];
					for (j = bigger; j >= value[i]; j--) {
						if (dp[j - value[i]] != -1) {
							int tmp = dp[j - value[i]] + 1;
							if (dp[j] == -1 || tmp < dp[j]) {
								dp[j] = tmp;
							}
						}
					}
				}
			}
			int ans = -1;
			for (i = w; i <= bigger; i++) {
				if (dp[i] != -1) {
					int need = i - w;
					if (change[need] != -1) {
						int tmp = dp[i] + change[need];
						if (ans == -1 || ans > tmp)ans = tmp;
					}
				}
			}
			if (ans != -1)cout << ans << endl;
			else cout << "impossible" << endl;
		}
	}



	return 0;
}

汽车加油问题

问题描述:

一辆汽车加满油后可行驶n 公里。旅途中有若干个加油站。设计一个有效算法,指出应在哪些加油站停靠加油,使沿途加油次数最少。并证明算法能产生一个最优解。

编程任务:

对于给定的n 和k 个加油站位置,编程计算最少加油次数。

数据输入:

由文件input.txt 给出输入数据。第一行有2 个正整数n 和k,表示汽车加满油后可行驶n 公里,且旅途中有k 个加油站。接下来的1 行中,有k+1 个整数,表示第k 个加油站与第k-1 个加油站之间的距离。第0 个加油站表示出发地,汽车已加满油。第k+1 个加油站表示目的地。

结果输出:

将编程计算出的最少加油次数输出到文件output.txt 。如果无法到达目的地,则输出”No Solution”。

输入文件示例输出文件示例

input.txt output.txt

7 7 4

1 2 3 4 5 1 6 6

#include<iostream>
using namespace std;
 
int main(){
    int n,k,i;
    cin>>n>>k;
    int dis;//到下一个加油站的距离
    int leave=n;//剩余油能跑的距离
    int top=0;//加油数目
    for(i=0;i<=k;i++)
    {
        cin>>dis;  //随输随处理
        if(leave<dis)    //剩下的油跑不到了
        {
            if(dis>n)//加满油也跑不到
            {
                printf("No Solution");  //没救了
                return 0;
            }
            top++;
            leave=n;  //油加满
        }
        leave-=dis;  //开车跑路
    }
    cout<<top;
    return 0;
}

最优分解问题

问题描述:

设n 是一个正整数。现在要求将n 分解为若干个互不相同的自然数的和,且使这些自然数的乘积最大。

编程任务:

对于给定的正整数n,编程计算最优分解方案。

数据输入:

由文件input.txt 提供输入数据。文件的第1 行是正整数n。

结果输出:

程序运行结束时,将计算出的最大乘积输出到文件output.txt 中。

输入文件示例 输出文件示例

input.txt output.txt

10 30

#include<iostream>
using namespace std;
 
int main() {
    int n;
    cin>>n;
    int x=n;
    int i=2,j=0,a[99999];
    while(x>=i) {
        a[j]=i;
        j++;
        x=x-i;
        i++;
    }
    int p=j;//记录分解的因数的个数
    j--;//最后一个a数组所在位置的下标
    while(x--) {
        a[j]++;
        j=(j-1+p)%p;//考虑到剩余的数大于分解的因数的个数的情况
    }
    int sum=1;
    for(int s=0; s<p; s++) {
        sum=sum*a[s];
    }
    cout<<sum<<endl;
 
    return 0;
}

程序存储问题

问题描述:

设有n 个程序{1,2,…, n }要存放在长度为L 的磁带上。程序i 存放在磁带上的长度是li,1≤i≤n 。程序存储问题要求确定这n 个程序在磁带上的一个存储方案,使得能够在磁带上存储尽可能多的程序。

编程任务:

对于给定的n 个程序存放在磁带上的长度,编程计算磁带上最多可以存储的程序数。

数据输入:

由文件input.txt 给出输入数据。第一行是2 个正整数,分别表示文件个数n 和磁带的长度L。接下来的1 行中,有n 个正整数,表示程序存放在磁带上的长度。

结果输出:

将编程计算出的最多可以存储的程序数输出到文件output.txt 。

输入文件示例输出文件示例

input.txt output.txt

6 50 5

2 3 13 8 80 20

#include <iostream>
#include <algorithm>
using namespace std;
int main() {
    int n, l, i, ct=0;
    cin>>n>>l;
    int num[n];
    for(i = 0; i < n; i++) {
        cin>>num[i];
    }
    sort(num, num+n);
    for(i = 0; i < n; i++) {
        if(num[i] <= l) {
            l -= num[i];
            ct++;
        }
    }
    cout<<ct<<endl;
    return 0;
}
  • 20
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值