实验四 贪心算法
一.实验目的
理解贪心算法的思想,并能对给定的问题能设计出分治算法予以解决。
二.实验基本步骤
- 选定实验题目,仔细阅读实验要求,设计好输入输出,按照分治法的思想构思算法,选取合适的存储结构实现应用的操作。
- 设计的结果应在Visual C++ 实验环境下实现并进行调试。(也可使用JAVA编程)
- 实验要有详细的测试记录,包括各种可能的测试数据。
三.实验内容
-
背包问题
给定n种物品和一个背包。物品i的重量是Wi,其价值为Vi,背包的容量为C。应如何选择装入背包的物品,使得装入背包中物品的总价值最大?
void Knapsack(int n, float M, float v[],float w[],float x[])
{
Sort(n,v,w);
int i;
for (i=1;i<=n;i++) x[i]=0;
float c=M;
for (i=1;i<=n;i++) {
if (w[i]>c) break;
x[i]=1;
c-=w[i];
}
if (i<=n) x[i]=c/w[i];//最后一个物品运行部分转入
} -
教材117页算法实现题4-11。删数问题。
给定一个高精度正整数a, 去掉其中k个数字后按原左右次序将组成一个新的正整数。对给定的a, k寻找一种方案,使得剩下的数字组成的新数最小。
解:应用贪心算法设计求解
(1) 设计要点
操作对象为n位高精度数,存储在数组a中。
在整数的位数固定的前提下,让高位的数字尽量小,整数的值就小。这就是所要选取的贪心策略。
每次删除一个数字,选择一个使剩下的数最小的数字作为删除对象。
当k=1时,对于n位数构成的数删除哪一位,使得剩下的数据最小。删除满足如下条件的a[i]:它是第一个a[i]>a[i+1]的数,如果不存在则删除a[n](最后一位数字,具体实现时请注意下标表示方法)。
当k>1(当然小于n),按上述操作一个一个删除。每删除一个数字后,后面的数字向前移位。删除一个达到最小后,再从头开始,删除第2个,依此分解为k次完成。
若删除不到k个后已无左边大于右边的降序或相等,则停止删除操作,打印剩下串的左边n-k个数字即可(相当于删除了若干个最右边的数字)。
import java.util.*;
public class test0411 {public static void main(String[] args) {
Scanner in=new Scanner(System.in);
int n;
int k;
int count=0;
n=in.nextInt();
k=in.nextInt();
int[] a=new int[1000];
for(int i=0;i<n;i++) {
a[i]=in.nextInt();
}
count=k;
while(k>0) {
int i=0;
while(i<n&&a[i]<a[i+1]) {
i++;} for(int j=i;j<n;j++) { a[j]=a[j+1]; //6break; } k--; } for(int i=0;i<n-count;i++) { System.out.print(a[i]); } }
}
-
教材115页算法实现题4-6。最优服务次序问题。
实现提示:贪心策略为最短服务时间优先。
import java.util.*;
public class test046 {
public static void main(String[] args) {
int[] time=new int[100];
int sum=0;
int max=0;
int k=0;
int p;
List<int[]>list=Arrays.asList(time);
Scanner in=new Scanner(System.in);
Scanner in1=new Scanner(System.in);
System.out.println(“输入一个整数”);
int a=in.nextInt();
System.out.println(“输入顾客所需的服务时间”);
for(int i=0;i<=a-1;i++) {
int b=in.nextInt();
time[i]=b;
}
for(int i=0;i<=a-1;i++) {
for(int u=0;u<a-1;u++) {
if(time[u]>time[u+1]) {
p=time[u];
time[u]=time[u+1];
time[u+1]=p;
}
}
}
System.out.println();
for(int i=1;i<=a-1;i++){//每个位置累加前面到自己
time[i]+=time[i-1];
}
for(int i=0;i<=a-1;i++) {
sum+=time[i];
}
System.out.println(sum/a);}
}
-
教材117页算法实现题4-9。虚拟汽车加油问题。
实现提示: 贪心策略为最远加油站优先。
import java.util.*;
public class test049 {public static void main(String[] args) {
int[] k=new int[100];
int oil;
int sum;
int count=0;
int kilo;
Scanner in=new Scanner(System.in);
System.out.println(“加满油能走几公里”);
oil=in.nextInt();
System.out.println(“有几个加油站”);
kilo=in.nextInt();
sum=oil;
for(int i=0;i<kilo+1;i++) {
k[i]=in.nextInt();
}
for(int i=0;i<kilo+1;i++) {if(k[i]>sum) { System.out.println("加油"); sum=oil; count++; } sum=sum-k[i]; } System.out.println(count+"加油次数");
}
}
- 多机调度问题 (选做题)
利用贪心法设计算法求解如下问题:
要求给出一种作业调度方案,使所给的n个作业在尽可能短的时间内由m台机器加工处理完成。约定,每个作业均可在任何一台机器上加工处理,但未完工前不允许中断处理。作业不能拆分成更小的子作业。
这个问题是一个NP完全问题,到目前为止还没有一个有效的解法。对于这一类问题,用贪心选择策略有时可以设计出较好的近似算法。
可以考虑以下的贪心策略:
(1)最长处理时间作业优先的贪心选择策略。
(2)最短处理时间作业优先的贪心选择策略。
(3)作业到达时间优先的贪心选择策略。
假设7个独立的作业由3台机器加工处理,各作业所需的处理时间为:{2,14,4,6,16,5,3},写出以上算法求解此问题的结果。