貪心演算法作業
桂 林 理 工 大 學
實 驗 報 告
班級 軟體工程16-1班 學號 3162052051116 姓名 張識虔 同組實驗者
實驗名稱 貪心演算法
一、實驗目的:
理解貪心演算法的思想,並能對給定的問題能設計出分治演算法予以解決。
二、實驗環境:
三、實驗內容:
1. 揹包問題
給定n種物品和一個揹包。物品i的重量是Wi,其價值為Vi,揹包的容量為C。應如何選擇裝入揹包的物品,使得裝入揹包中物品的總價值最大? (說明,以下演算法與教材147頁給出的演算法思想是一樣的,教材上的演算法事先對物品資訊進行了排序)
#include<iostream>
using namespace std;
void Sort(int n,float v[],float w[])
{
int i;
int j;
float t;
for(i=1;i<=n-1;i++){
for(j=i;j<=n;j++){
if(v[i]/w[i]<v[j]/w[j]){
t=v[i];
v[i]=v[j];
v[j]=t;
t=w[i];
w[i]=w[j];
w[j]=t;
}
}
}
}
void Knapsack(int n,float M,float v[],float w[],float x[])
{
Sort(n,v,w);
int i;
int j;
float max;
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];//最後一個物品選擇部分裝入
cout<<"選擇依次裝入揹包的物品屬性為: "<<endl;
for(i=1;i<=n;i++){
if(x[i]!=0.0){
cout<<"w="<<w[i]<<","<<"v="<<v[i]<<endl;
max=max+v[i]*x[i];
if(x[i]!=1.0){
cout<<"最後裝入的物品選擇裝入物品的"<<x[i]*100.0<<"%"<<endl;
}
}
}
cout<<endl;
cout<<"最大價值MaxValue="<<max<<endl;
}
int main()
{
int n,c,i;
float v[20],w[20],x[20];
cout<<"輸入 物品的數量 和 揹包的容量: "<<endl;
cin>>n>>c;
cout<<"輸入物品的重量和價值:"<<endl;
for(i=1;i<=n;i++){
cout<<"物品"<<i<<"的重量和價值:";
cin>>w[i]>>v[i];
}
cout<<endl;
Knapsack(n,c,v,w,x);
return 0;
}
2. 教材170頁第18題。刪除數字求最小值
給定一個n位正整數a, 去掉其中k個數字後按原左右次序將組成一個新的正整數。對給定的a, k尋找一種方案,使得剩下的數字組成的新數最小。
提示:應用貪心演算法設計求解
操作物件為n位正整數,有可能超過整數的範圍,儲存在陣列a中,陣列中每一個數組元素對應整數的一位數字。
在整數的位數固定的前提下,讓高位的數字儘量小,整數的值就小。這就是所要選取的貪心策略。
每次刪除一個數字,選擇一個使剩下的數最小的數字作為刪除物件。
當k=1時,對於n位數構成的數刪除哪一位,使得剩下的資料最小。刪除滿足如下條件的a[i]:它是第一個a[i]>a[i+1]的數,如果不存在則刪除a[n]。
當k>1(當然小於n),按上述操作一個一個刪除。每刪除一個數字後,後面的數字向前移位。刪除一個達到最小後,再從頭即從串首開始,刪除第2個,依此分解為k次完成。
若刪除不到k個後已無左邊大於右邊的降序或相等,則停止刪除操作,列印剩下串的左邊n−k個數字即可(相當於刪除了若干個最右邊的數字)。
#include <iostream>
#include<algorithm>
#define N 100
using namespace std;
bool cmp(int a,int b)
{
if(a>b)
return true;
return false;
}
int main()
{
int a[N],b[N],c[N];
int n,i,k,j,x=1;
int flag=1;
cout<<"輸入多少位數:"<<endl;
cin>>n;
cout<<"輸入的數值:";
for(i=1;i<=n;i++){
cin>>a[i];
b[i]=a[i];
}
for(i=1;i<=n;i++){
if(a[i]==a[n-i])
flag=0;
}
cout<<"需要刪除幾個數字:";
cin>>k;
sort(a+1,a+n+1,cmp);
for(i=1;i<=n;i++){
for(j=k+1;j<=n;j++){
if(b[i]==a[j]){
c[x]=b[i];
x++;
}
}
}
cout<<"刪除後的數值為";
if(flag){
for(i=1;i<=x-1;i++){
cout<<c[i];
}
}
else{
for(i=1;i<=n-k;i++){
cout<<b[i];
}
}
return 0;
}
數字都不相同時
數字都相同時
3.設有n個顧客同時等待一項服務。顧客i需要等待的服務時間為ti(1<=i<=n)。共有s處可以提供此服務。應如何安排n個顧客的服務次序才能使平均等待時間達到最小?平均等待時間是n個顧客等待服務時間的總和除以n。
#include<stdio.h>
void sort(int a[],int n)
{
int i;
int j;
int t;
for(i=0;i<n-1;i++){
for(j=i;j<n;j++){
if(a[i]>a[j]){
t=a[i];
a[i]=a[j];
a[j]=t;
}
}
}
}
void greedy(int n,int s,int time[])
{
int i;
int sum;
int *p=new int[s];
sum=0;
for(i=0;i<n;i++){
p[i]=0;
}
for(i=0;i<n;i++){
p[i%s]+=time[i];
sum=sum+p[i%s];
}
printf("%.3lf\n",sum/(n*1.0));
}
int main()
{
int n;
int s;
int i;
int time[50];
printf("請輸入顧客數量 服務處數量\n");
scanf("%d %d",&n,&s);
printf("輸入各個顧客的服務時間\n");
for(i=0;i<n;i++){
scanf("%d",&time[i]);
}
sort(time,n);
printf("平均等待時間:");
greedy(n,s,time);
return 0;
}
四、心得體會: