贪心算法实验(第三次)
会场安排问题
问题描述:
假设要在足够多的会场里安排一批活动,并希望使用尽可能少的会场。设计一个有效的贪心算法进行安排。(这个问题实际上是著名的图着色问题。若将每一个活动作为图的一个顶点,不相容活动间用边相连。使相邻顶点着有不同颜色的最小着色数,相应于要找的最小会场数。)
编程任务:
对于给定的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;
}