雪影藍楓如果可以,每個人都願意走向優秀!當你下定了決心時,就意味著你要比別人付出更多! by @scau_JosephHDU ACM 1050 Moving Tables
Problem Description
The famous ACM (Advanced Computer Maker) Company has rented a floor of a building whose shape is in the following figure.
The floor has 200 rooms each on the north side and south side along the corridor. Recently the Company made a plan to reform its system. The reform includes moving a lot of tables between rooms. Because the corridor is narrow and all the tables are big, only
one table can pass through the corridor. Some plan is needed to make the moving efficient. The manager figured out the following plan: Moving a table from a room to another room can be done within 10 minutes. When moving a table from room i to room j, the
part of the corridor between the front of room i and the front of room j is used. So, during each 10 minutes, several moving between two rooms not sharing the same part of the corridor will be done simultaneously. To make it clear the manager illustrated the
possible cases and impossible cases of simultaneous moving.
For each room, at most one table will be either moved in or moved out. Now, the manager seeks out a method to minimize the time to move all the tables. Your job is to write a program to solve the manager’s problem.
InputThe input consists of T test cases. The number of test cases ) (T is given in the first line of the input. Each test case begins with a line containing an integer N , 1<=N<=200 , that represents the number of tables to move. Each
of the following N lines contains two positive integers s and t, representing that a table is to move from room number s to room number t (each room number appears at most once in the N lines). From the N+3-rd line, the remaining test cases are listed in the
same manner as above.
OutputThe output should contain the minimum time in minutes to complete the moving, one per line.
Sample Input3 4 10 20 30 40 50 60 70 80 2 1 3 2 200 3 10 100 20 80 30 50
Sample Output10 20 30
資料 Input1 1975 154
125 158
176 48
196 65
21 171
15 170
17 100
61 116
3 189
98 104
112 19
163 66
42 14
81 168
53 165
36 143
84 140
105 199
195 151
資料 Input150
解題思路 這題普遍有兩種做法一種就是找到房間覆蓋次數最多的數輸出即可;一種是用貪心,也是因為開始學貪心我才開始找到這題的,沒想到碰壁碰得那麼嚴重,看關於貪心的相關資料後貪心的一個特點是找當前的最優值,當然這個部分最優值能夠滿足最終的整體最優值,所以這題我開始認為的時候是每次移動的時候找到儘可能多的可以同時移動的房間,這樣到最後需要移動的次數會達到最小,我認為找到儘可能多的移動房間是當前的最優值,而儘可能找到最多房間的方法,無疑剛學貪心的童鞋都應該見過更典型的貪心基礎的例子,比如說 活動安排問題(《電腦演算法設計與分析》)等,這種儘可能找最多移動房間數目(也就是對應的最多的活動節目數量)就是根據活動結束的時間排序,因為這樣才能為未安排活動留下儘可能多的時間,同樣的道理,這題我選擇按房間尾數小的數排序也是希望留下的走廊的路徑長度更長使儘可能多的房間可以移動。 如果你說只給你一次移動的機會,要你找到移動儘可能多的房間,我這種按照尾數排序的方式跟活動安排的例子無異都是正確的,但是這題不一樣,最終你是要將所有的需要移動的房間移完,對於活動安排這個例子,也就意味著你必須將活動節目表上的節目全部安排完,問你最少需要多少天,這是同樣的概念。 在網上搜了題解,沒有人說明到底為什麼要按照房間首位置排序,當然我也沒理由否認這是不行的,我按照房間尾數排序無非是我找到了這麼一個理由——餘留更多的走廊長度,所以我就選擇了這個方法,後來找到了一個Case,也就是上面我放上去的測試資料,根據兩種排序方式輸出,發現前面房間的移動情況會影響接下來的房間移動,這兩天想了一段時間也每個結果 我從另外一個角度想,如果按房間尾數排序的話,那麼在第二次遍曆的時候第一個找到的房間的起始號並不是最前的,這時不是最優的,你要從總體上來看,你以為每次找到儘可能多的房間,對一次的遍曆從房間尾號排序確實達到了這樣的目的,但你的整體目的不是這樣的,因為你最終還是要把所有的房間找完,並不是說僅是找最多的一次,你還要顧及後面的讓每一次都儘可能找得更多的房間。所以不管前幾次怎樣,你現在要找的這一次需要越靠前開始找。 形式上突然想到這題有點像0-1背包,你知道0-1背包是不能用貪心的方法解決的,下面是一個可以試用貪心演算法解的題目,貪心解的確不錯,可惜不是最優解。例子摘抄於:http://www.worlduc.com/blog2012.aspx?bid=5605728 [背包問題] 有一個背包,背包容量是M=150。有7個物品,物品不可以分割成任意大小。要求儘可能讓裝入背包中的物品總價值最大,但不能超過總容量。 物品 A B C D E F G 重量 35 30 60 50 40 10 25 價值 10 40 30 50 35 40 30 分析: 目標函數: ∑pi最大 約束條件是裝入的物品總重量不超過背包容量:∑wi<=M( M=150) (1)根據貪心的策略,每次挑選價值最大的物品裝入背包,得到的結果是否最優? (2)每次挑選所佔重量最小的物品裝入是否能得到最優解? (3)每次選取單位重量價值最大的物品,成為解本題的策略。 值得注意的是,貪心演算法並不是完全不可以使用,貪心策略一旦經過證明成立後,它就是一種高效的演算法。貪心演算法還是很常見的演算法之一,這是由於它簡單易行,構造貪心策略不是很困難。可惜的是,它需要證明後才能真正運用到題目的演算法中。 一般來說,貪心演算法的證明圍繞著:整個問題的最優解一定由在貪心策略中存在的子問題的最優解得來的。 對於例題中的3種貪心策略,都是無法成立(無法被證明)的,解釋如下:
(1)貪心策略:選取價值最大者。 反例: W=30 物品: A B C 重量:28 12 12 價值:30 20 20 根據策略,首先選取物品A,接下來就無法再選取了,可是,選取B、C則更好。
(2)貪心策略:選取重量最小。它的反例與第一種策略的反例差不多。
(3)貪心策略:選取單位重量價值最大的物品。 反例: W=30 物品: A B C 重量:28 20 10 價值:28 20 10 根據策略,三種物品單位重量價值一樣,程式無法依據現有策略作出判斷,如果選擇A,則答案錯誤。 【注意:如果物品可以分割為任意大小,那麼策略3可得最優解】 對於選取單位重量價值最大的物品這個策略,可以再加一條最佳化的規則:對於單位重量價值一樣的,則優先選擇重量小的!這樣,上面的反例就解決了。 但是,如果題目是如下所示,這個策略就也不行了。 W=40 物品:A B C 重量:25 20 15 價值:25 20 15 附:本題是個NP問題,用貪進法並不一定可以求得最優解,以後瞭解了動態規划算法後本題就有了新的解法。 上面這個例子很經典,它跟背包問題作對比說明貪心跟動態規劃的區別,而杭電的這題是否也跟上面這個0-1背包有相同的地方,即我的做法是不是也是按第一種策略之後最後才得出錯誤的答案
儘力地說明最終還是要靠證明,抱歉,不會,所以如果你看了這個題解,然後知道怎樣證明的話,希望你能夠高抬貴手留下言,好讓剛學貪心的我能夠對此有深刻的理解
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<algorithm> 5 #define SIZE 404 6 7 using namespace std; 8 9 typedef struct item{10 int begin, end;11 }item;12 item room[SIZE];13 bool visit[SIZE];14 int n;15 16 bool cmp(const item& a, const item& b)17 {18 return a.begin < b.begin;19 }20 21 void Traverse(int cnt, int sum)22 {23 if(sum == n)24 {25 printf("%d\n", cnt*10);26 return;27 } 28 int temp = 0, count = 0;29 for(int i=0; i<n; ++i)30 {31 if(!visit[i] && temp < room[i].begin)32 {33 count++;34 temp = room[i].end;35 visit[i] = true;36 }37 }38 Traverse(cnt+1, sum+count);39 }40 41 int main()42 {43 #ifndef ONLINE_JUDGE44 freopen("input.txt", "r", stdin);45 #endif46 int T, left, right;47 scanf("%d", &T);48 while(T--)49 {50 scanf("%d", &n);51 for(int i=0; i<n; ++i)52 {53 scanf("%d", &left);54 room[i].begin = left = left + (left % 2);55 scanf("%d", &right);56 room[i].end = right = right + (right % 2);57 if(left > right)58 {59 room[i].begin = right;60 room[i].end = left;61 }62 }63 memset(visit, false, sizeof(visit));64 sort(room, room+n, cmp);65 Traverse(0, 0);66 }67 }
本文轉自:http://www.cnblogs.com/liaoguifa/p/3198051.html