實驗四 貪心演算法
希望有大佬指教,蟹蟹
一、實驗目的:
理解貪心演算法的思想,並能對給定的問題能設計出分治演算法予以解決。
二、實驗環境:
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;
}
執行結果: