某农业学校 算法设计与分析实验4-贪心算法

1. 会场安排问题--贪心

问题描述:

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

编程任务:

  对于给定的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<bits/stdc++.h>
using namespace std;
int k,ans,a[1010];
struct pd
{
	int s,e;
}p[1010];
/*
5
1 23
12 28
25 35
27 80
36 50
*/
bool cmp1(pd a,pd b)
{
	if(a.s==b.s)
	return a.e<b.e;
	else
	return a.s<b.s;
}

int main()
{
	cin>>k;
	for(int i=1;i<=k;i++)
	{
		cin>>p[i].s>>p[i].e;
	}
	sort(p+1,p+k+1,cmp1);
	for(int i=1;i<=k;i++)
	{
		int temp=ans;
		for(int j=0;j<=temp;j++)//依次看几个组中可以融入 
		{
			if(p[i].s>=a[j])
			{
				if(a[j]==0)
				{
					ans++;
				}
				a[j]=p[i].e;
				break;
			}
		}
	}
	cout << ans;
	return 0;
}

2. 硬币找钱问题--贪心

问题描述:

  设有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<bits/stdc++.h>
using namespace std;
/*
2 4 2 2 1 0   0.95
2 4 2 0 1 0   0.55
0 0 0 0 0 0
*/
int coins[6],num=0,pay;
int v[6]={5,10,20,50,100,200};
int z[7] ={0,5,10,20,50,100,200};
int money=v[0]-z[0];	   //实际支付=支付-找零

int contains(int a)
{
	for(int i=0;i<6;i++)
	{
		if(v[i]==a && coins[i]>0)
			return i;
	}	
	return -1;
}

void guo()
{
	for(int i=5;i>=0;i--)
	{
		if(coins[i]>0) 
		{
			for(int j=0;j<=i;j++)
			{
				money=v[i]-z[j]; 
				if(pay>=money)
				{
					if(coins[i]>=pay/money) 
					{
						int temp=pay/money; 
						num+=temp*2;
						if(contains(money)!=-1)
						{
							temp=min(temp,coins[contains(money)]);
							num-=temp;
							coins[contains(money)]-=temp;
						}
						else
							coins[i]-=pay/money; 
						pay=pay%money;			 
						if(contains(v[i])==-1)
							break; 
					}
					else 
					{
						num+=coins[i];
						pay=pay-v[i]*coins[i];
						coins[i]=0;
					}
				}
			}
		}
	}
}

int main()
{
	while(1)
	{
		num=0;
		int flag=0;
		for(int i=0;i<6;i++)
		{
			cin >> coins[i];
			if(coins[i]!=0)
			{
				flag=1;
			}
		}
		if(flag==0)
		{
			return 0;
		}
		double t;
		cin >>t;
		pay=(int)(t*100);
		 
		guo();
		
		if(num==0 || pay!=0)
		{
			cout <<"impossible\n";
		}
		else
		{
			cout <<num<<endl;
		}
	}
}

3. 汽车加油问题---贪心

问题描述:

  一辆汽车加满油后可行驶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                 

7 7                                  

1 2 3 4 5 1 6 6

output.txt

 4

#include<bits/stdc++.h>
using namespace std;
/*
7 7
1 2 3 4 5 1 6 6
*/
int n,k,a[1010],ans;

int main()
{
	cin>>n>>k;
	int flag=0;
	for(int i=1;i<=k+1;i++)
	{
		cin>>a[i];
		if(a[i]>n)
			flag=1;
	}
	if(flag==1)
	{
		cout << "No Solution";
		return 0;
	}
	int temp=n;
	for(int i=1;i<=k+1;i++)
	{
		temp=temp-a[i];
		if(temp-a[i+1]<0)
		{
			ans++;
			//cout << i<<endl;
			temp=n;
		}
	}
	cout << ans;
	return 0;
}

4. 最优分解问题--贪心

问题描述:

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

编程任务:

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

数据输入:

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

结果输出:

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

输入文件示例 

input.txt 

10               

输出文件示例

output.txt

30

#include<bits/stdc++.h>
using namespace std;
int n,ans=1,a[1010]={0};

int main()
{
	cin>>n;
	int i=1,j;
	a[0]=1;
	while(n>a[i-1]) //最初分配的因子
    {
        a[i]=a[i-1]+1;
        n-=a[i];
        i++;
    }
    while(n>0)  //剩下的数依次减一,加在已分配好的因子上
    {
        for(j=1;j<i;j++)
        {
            a[i-j]++;
            n--;
            if((i-j)==0)
            {
            	j=1;
            	break;
			}
            if(n==0)
                break;  
        }
    }
    for(j=1;j<i;j++)
    {
    	ans=ans*a[j];
	}
	cout << ans;
	return 0;
}

5. 程序存储问题----贪心算法

问题描述:

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

编程任务:

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

数据输入:

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

结果输出:

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

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

input.txt

6 50                                  

2 3 13 8 80 20

output.txt

5

#include<bits/stdc++.h>
using namespace std;
int n,l,a[1010],ans;
/*
6 50    
2 3 13 8 80 20
*/

int main()
{
	cin>>n>>l;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++)
	{
		if(l-a[i]>0)
		{
			l-=a[i];
			ans++;
		}
	}
	cout << ans;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值