演算法設計與分析入門篇 貪心法3

2021-07-02 15:30:44 字數 3128 閱讀 2345

課程排程

題目內容:

有 n 個人,要完成 2 門課程。其中第 i 個人學習一門課程所需要的時間是 ti。

每個人同一時刻只能修一門課程,每門課程同一時刻只能被乙個人修,中間不能中斷。

問所有人都修完 2 門課程,至少需要多少時間。

輸入格式:

輸入的第一行包含乙個整數 n(1 <= n <= 1000000)。

接下來的一行包含 n 個整數 (1 <= ai <= 1000000000),表示每門課程的時間。

輸出格式:

輸出一行表示對應的答案。

輸入樣例:

3 2 2 2

3 4 1 2

4 1 3 2 1

輸出樣例:

6 8

7時間限制:2000ms記憶體限制:128000kb

思路是模擬兩個課程不斷挑選最合適的人來學,最合適的人 兩門課都沒學,並且學的時間是剩餘最長的。其次學完一門,學的時間是剩餘最長的。

#include 

#include

using

namespace

std;

void max(int& class1, int class2, int &sum, int k, vector

> &p)

}}int main()

while (sum != 2 * n)

if (class2 < 0 || p[class2][1] == 0)

if (class1 >= 0 && p[class1][0]>0)

if (--p[class1][0] == 0)

sum++;

if (class2 >= 0 && p[class2][1]>0)

if (--p[class2][1] == 0)

sum++;

count++;

}cout

<< count << "\r\n";

}system("pause");

}

用例1過了,2超時

#include 

#include

using

namespace

std;

void max(int& class1, int class2, int &sum, int k, vector

> &p)

}}int main()

while (sum != 2 * n)

if (class2 < 0 || p[class2][1] == 0)

if (class1 >= 0 && p[class1][0]>0)

if (--p[class1][0] == 0)

}if (class2 >= 0 && p[class2][1]>0)

if (--p[class2][1] == 0)

}count++;

}cout

<< count << "\r\n";

}system("pause");

}

用例1過了,2超時

再改

#include 

#include

using

namespace

std;

void max(int& class1, int class2, int &sum, int k, vector

> &p)

}}int min(int a, int b)

int main()

while (sum != 2 * n)

if (class2 < 0 || p[class2][1] == 0)

int classmin;

if (class1 == -1)

else

if (class2 == -1)

else

if (class1 >= 0)

if (p[class1][0] == 0)

}if (class2 >= 0)

if (p[class2][1] == 0)

}count += classmin;

}cout

<< count << "\r\n";

}system("pause");

}

還是超時,越改越慢。然後就發現這道題其實很簡單,

思路,求出學一門課時間最長的人所需要的時間,即給的陣列的最大值max。求出陣列的和,結果就是2*max 與陣列的和兩個數中大的那個。

**如下:

#include

using namespace std;

int main()

else

}if (max

>

sum)

cout <<2*

max<<

"\r\n";

else

cout <<

max+

sum<<

"\r\n";

}system("pause");

}

證明方法:

為了簡單說明先排個序,實際上不用。

k1 k2 k3 …………kn 從大到小

先說一下,學完的最短時間就是陣列的和,而時間會比它長是因為第一節課與第二節課產生了衝突,即乙個人正在學第一節課,而第二節課沒學的也只剩他乙個了,所以要學完第二節課必須等他學完第一節課。

第一門課從k1開始學 k1 k2 k3….

第二門課從kn開始學 kn kn-1 kn-2 ……..

則兩門課會相遇,設在第m個人處相遇即在km處

若m!=1,則第二門課從km+1跳到k1處,由於k1>=km,所以當第乙個人的第二門課學完後第m個人的第一門課也一定學完。則第一門課與第二門課就不會有衝突了。(任意乙個人至少學了一門課)所用時間為 k1 + k2 + k3………+kn

若m==1(k1>k2+k3+….+kn),則第二節課要等第乙個人把第一節課學完才能讓他學習第二節課,第乙個人學完第一節課後再學第二節,因為(k1>k2+k3+….+kn),所以當他學完第二節課後,其他人也早將第一節課學完了,所用時間為 2*k1

上面程式中的 sum 是 k2+k3+….+kn,max 是 k1。

演算法設計與分析之貪心法

貪心法總是做出在當前看來最好的選擇,一旦做出了選擇,不管將來有什麼結果,這個選擇都不會改變。也就是說貪心法並不從整體最優考慮,它所作出的選擇只是在某種意義上的區域性最優選擇。當然,希望貪心法得到的最終結果也是整體最優的。雖然貪心法不能對所有問題都得到整體最優解,但對許多問題它能產生整體最優解。幾點說...

演算法設計與分析入門篇 分治作業 1

題目內容 給定 n 個數組成的陣列,求其逆序對的總數。逆序對定義為,存在 i,j 滿足 i j 且 a i a j 的二元組的數目。輸入格式 第一行包含乙個整數,表示陣列的項數。接下來的一行,包含 n 個數 leq 100000 依次表示 ai ai 109 輸出格式 輸出一行表示對應的答案。輸入樣...

演算法設計與分析入門篇 動態規劃 2

2括號子串行 a 10分 題目內容 一段括號序列被稱為平衡的,如果對於任意字首,左括號的數目都不小於右括號。給定一段括號序列,問有多少括號子串行是平衡的。內容相同但位置不同的算兩種。輸入格式 多組測試資料,每組測試資料報含一行乙個括號序列,括號序列的長度 100。輸出格式 輸出一行表示答案模 10 ...