1. 程式人生 > 其它 >實驗四 貪心演算法

實驗四 貪心演算法

希望有大佬指教,蟹蟹
一、實驗目的:
理解貪心演算法的思想,並能對給定的問題能設計出分治演算法予以解決。

二、實驗環境:
Visual C++ 實驗環境

三、實驗內容:
(寫出主要的內容)
1.最優服務次序問題。
問題描述:設有n個顧客同時等待一項服務,顧客i需要的服務時間為ti,(1<=i<=n)。應如何安排n個顧客的服務次序才能使平均等待時間達到最小?(平均等待時間是n個顧客等待服務時間總和除以n)
輸入:第一行為一個正整數n,表示有n個顧客
第二行為n個正整數,表示n個顧客需要的服務時間
輸出:最小平均等待時間。
程式碼:

#include<iostream>
#include<
algorithm
>
#include <iomanip> //輸出有效數字的標頭檔案 using namespace std; int t[10005]; int main() { int n; cin>>n; int i; for(i=1;i<=n;i++) //迴圈輸入服務時間 cin>>t[i]; sort(t+1,t+1+n); int sum=0,tmp=0; for(i=1;i<=n;i++) { sum+=tmp; sum+=t[i]; tmp+=t[i]; } double ans=0; ans=(double)sum*1.0/n; cout.setf(ios::fixed); cout.precision(3); //三位有效數字 cout<<ans<<endl; return 0; }

執行結果:
在這裡插入圖片描述

2.多處最優服務次序問題。
問題描述:設有n個顧客同時等待一項服務,顧客i需要的服務時間為ti,(1<=i<=n)。共有s處可以提供此項服務。應如何安排n個顧客的服務次序才能使平均等待時間達到最小?
輸入:第一行為兩個正整數n和s
第二行為n個正整數,表示n個顧客需要的服務時間
輸出:最小平均等待時間。
程式碼:

#include<iostream>
#include<vector>
#include<algorithm>
#include<iomanip>
using namespace std;

double greedy(vector<
int
>
client,int s) //client為顧客等待的duilie,s為視窗總數 { vector<int>service(s+1,0); //服務視窗每一個顧客等待的時間 vector<int>sum(s+1,0); //服務視窗顧客等待的時間總和 int n=client.size(); sort(client.begin(), client.end()); int i=0,j=0; while(i<n) { service[j]+=client[i]; sum[j]+=service[j]; i++; j++; if(j==s) j=0; //注意,j==num,不是num-1,因為j++在後 } double t=0; for(i=0;i<s;i++)//計算所有視窗時間服務總和 t+=sum[i]; return t/n; } int main() { int i,n,s; cin>>n>>s; vector<int>client(n,0); for(i=0;i<n;i++) cin>>client[i]; double ans=0; ans=greedy(client,s); cout.setf(ios::fixed); cout.precision(3); cout<<ans<<endl; return 0; }

執行結果:
在這裡插入圖片描述

3.最優分解問題。
問題描述:設n是一個正整數,要求將n分解為若干互不相同的自然數之和,且這些自然數的乘積最大。
輸入:正整數n
輸出:計算的最大乘積。
如輸入10,則輸出30.
提示:若a+b=const ,則a-b的絕對值越小,ab值越大。貪心策略:將n分成從2開始的連續自然數之和,如果最後剩下一個數,則將此數在後項優先的方式下均勻地分給前面各項。
程式碼:

#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
int main()
{
	int i,n,n1,n2,n3,s=0;
    priority_queue<int,vector<int>,less<int> >a;  //less表示大頂堆優先佇列, 注意最後不能連起來>>不然會被視為移位運算子
    cin>>n;
    for(i=2;;i++)//從2開始累加
	{
		s+=i;
        a.push(i);
        if(s>n)
		{
			n1=a.top();    //此時隊首是多放入的"錯數"
            a.pop();//彈出錯數
            s-=n1;
            n2=n-s;
            n3=a.top();
            break;
		}
	}
    int b[200],len; 
    for(i=0;!a.empty();i++)  //將佇列中數放入b陣列中,此時b陣列前面數大後面數小
	{
		b[i]=a.top();
        a.pop();
	} 
    len=i;
    sort(b,b+len);//將b陣列排序後變為前面數小後面數大
    int j=0; 
    while(1)//迴圈定位換掉哪個數
	{
		if(b[j]+n2>n3)
			break;
        j++;
	}
    b[j]=b[j]+n2;//換數
    sort(b,b+len);  //換掉數後可能打破陣列從小到大遞增的順序,因此還需排序一次
    int sum=1;
    for(i=0;i<len;i++)
		sum*=b[i];
    cout<<sum<<endl;
	return 0;
}

執行結果:
在這裡插入圖片描述

4.多機排程問題
利用貪心法設計演算法求解如下問題:
要求給出一種作業排程方案,使所給的n個作業在儘可能短的時間內由m臺機器加工處理完成。約定,每個作業均可在任何一臺機器上加工處理,但未完工前不允許中斷處理。作業不能拆分成更小的子作業。
這個問題是一個NP完全問題,到目前為止還沒有一個有效的解法。對於這一類問題,用貪心選擇策略有時可以設計出較好的近似演算法。
可以考慮以下的貪心策略:
(1)最長處理時間作業優先的貪心選擇策略。
(2)最短處理時間作業優先的貪心選擇策略。
(3)作業到達時間優先的貪心選擇策略。
假設7個獨立的作業由3臺機器加工處理,各作業所需的處理時間為:{2,14,4,6,16,5,3},寫出以上演算法求解此問題的結果。
最長處理時間優先程式碼:

#include <iostream>
#include <algorithm>
using namespace std;
struct A
{
	int time;
}a[1000];
struct B
{
	int time;
}b[1000] = {0};

int cmp(A a, A b) 
{
	return a.time > b.time;
}
int cm(B a, B b) 
{
	return a.time < b.time;
}
int main() 
{
	int j, i, n, m, t = 0;
	cin >> n >> m;
	for (i = 0; i < n; i++)
		cin >> a[i].time;
	sort(a, a + n, cmp);
	for (j = 0; j < n; j++)
	{
		if (j == n)
			break;
		b[0].time += a[j].time;
		if (b[0].time>t)
			t = b[0].time;
		sort(b, b + m , cm);
	}
	cout << t << endl;
	return 0;
}

執行結果:
在這裡插入圖片描述

最短處理時間優先程式碼:

#include <iostream>
#include <algorithm>
using namespace std;
struct A
{
	int time;
}a[1000];
struct B
{
	int time;
}b[1000] = {0};

int cmp(A a, A b) 
{
	return a.time < b.time;  //與第一個相反
}
int cm(B a, B b) 
{
	return a.time < b.time;
}
int main() 
{
	int j, i, n, m, t = 0;
	cin >> n >> m;
	for (i = 0; i < n; i++)
		cin >> a[i].time;
	sort(a, a + n, cmp);
	for (j = 0; j < n; j++)
	{
		if (j == n)
			break;
		b[0].time += a[j].time;
		if (b[0].time>t)
			t = b[0].time;
		sort(b, b + m , cm);
	}
	cout << t << endl;
	return 0;
}

執行結果:
在這裡插入圖片描述

作業到達時間優先程式碼:

#include <iostream>
#include <algorithm>
using namespace std;
struct A
{
	int time;
}a[1000];
struct B
{
	int time;
}b[1000] = {0};

int cm(B a, B b) 
{
	return a.time < b.time;
}
int main() 
{
	int j, i, n, m, t = 0;
	cin >> n >> m;
	for (i = 0; i < n; i++)
		cin >> a[i].time;
	for (j = 0; j < n; j++)
	{
		if (j == n)
			break;
		b[0].time += a[j].time;
		if (b[0].time>t)
			t = b[0].time;
		sort(b, b + m , cm);
	}
	cout << t << endl;
	return 0;
}

執行結果:
在這裡插入圖片描述