POJ1083 Moving Tables
題目分析:初看似乎像貪心算法中的活動安排問題,不同的是這里的所有活動(相當于搬桌子的距離)都需要安排。
有四種貪心策略:最短優先,最長優先,最早開始時間優先,最早結束時間優先。活動安排問題采用的是最早結束時間優先。此題要求所有活動都被安排,直觀的想同時進行的活動相互之間的間隔最小最好??梢宰C明最早開始時間優先滿足要求。
證明:令S = P1,P2,P3,P4,P5是滿足最早開始時間優先的一輪安排。即P1是所有活動中最早開始的,P2是在P1結束之后才開始的所有活動中最早開始的,依次類推。
假設存在最優解A不包含上述S的安排。我們要證明存在一個等價的最優解A‘包含上述的S安排。
由于P1是所有活動中最早開始的,所以A中必存在以P1開始的一輪安排,令為T = P1, T2, T3, T4,...Tn。
同時在A中,令包含 P2的一輪安排為B = B1,B2,...,P2,Bk,Bk+1,.. Bm。
由與P2是與P1相容活動中最早開始的,所以可以交換T2, T3, T4,...Tn與P2,Bk,Bk+1,.. Bm。得到新的安排T‘ = P1,P2,Bk,Bk+1,.. Bm和B' =?B1,B2,...,T2, T3, T4,...Tn。
繼續尋找包含P3的安排,依次類推,可以得到包含S的一個最優解A'。所以,任何最優解都可以轉換為使用最早開始時間優先構造的解。證畢。
先排序O(nlogn),然后每次查找(使用二分查找O(logn))相容的最早開始活動,總復雜度O(nlogn)。由于數量很少,使用選擇排序和線性查找即可。
#include <iostream> using namespace std; int main(){int n,c;int a,b;cin>>n;while(n>0){n--;cin>>c;int table[200][2];for(int i=0; i<c; i++){cin>>a>>b;a = (a-1)/2;b = (b-1)/2;//小的在前if(a<b){table[i][0] = a;table[i][1] = b;}else{table[i][0] = b;table[i][1] = a;}}//選擇排序for(int i=0;i<c-1;i++){int f = i,max = table[i][0];for(int j=i+1;j<c;j++){if(table[j][0] < table[f][0]){max = table[j][0];f = j;}}a = table[i][0];b = table[i][1];table[i][0] = table[f][0];table[i][1] = table[f][1];table[f][0] = a;table[f][1] = b;}int cnt = 0;int i;int newstart;//每次構造一輪最優安排while(true){i=0;//找第一個活動while(i<c && table[i][0]==-1)i++;if(i==c)break;newstart = table[i][1];//不能重合table[i][0]=-1;//安排過了的置為-1i++;//線性查找while(true){while(i<c && (table[i][0]<=newstart || table[i][0]==-1))i++;if(i==c)break;newstart = table[i][1];table[i][0]=-1;i++;}cnt++;}cout<<cnt*10<<endl;}return 0; }但是,使用貪心解法相當于構造了一個最有解,題目要求的是最小組數。明顯求最優解的復雜度>=求最小組數的復雜度。
顯然,最小安排組數>=活動的最大重合數。猜想最小安排組數==活動的最大重合數,下面來證明。令P(m)為最大重合數為m的最小安排組數。
假設P(m) = m。下面用數學歸納法證明。
顯然P(1)=1成立,即所有活動都不與其他活動重合。
假設P(k)=k成立;
則對P(k+1),令P(k+1)中有k+1個重合活動的區間為[s1,t1] [s2,t2]...[sn,tn]。則對[s1,t1]中的任意一個活動a1,都可以在[s2,t2].中找到至少一個活動不與a1重合(否則[s2,t2].中共有k+1個活動都與a1重合,則構成一個有k+2個重合活動的區間,矛盾),同時[s1,t1]中去除任意一個活動后,該區間的重合活動數減為k個。由以上兩點,可以構造一輪相互不重合的活動安排,使去掉這些活動后,[s1,t1] [s2,t2]...[sn,tn]區間的重合活動數都減為k。所以有P(k+1) = P(k)+1=k+1。命題得證。
復雜度為O(nm)。其中m是整個區間中需要統計的點數。
代碼如下:
#include <iostream> #include <math.h> #include <string.h> using namespace std; int main(){int n,c;int a,b;cin>>n;while(n>0){n--;cin>>c;int count[200];memset(count,0,sizeof(count));for(int i=0; i<c; i++){cin>>a>>b;if(a>b){int t = a;a = b;b = t;}a=(a-1)/2;b=(b-1)/2;for(;a<=b;a++){count[a]++;}}int max = 0;for(int j=0;j<200;j++){if(count[j]>max)max=count[j];}cout<<max*10<<endl;}return 0; }題目:時間限制: 1000ms 內存限制: 65536kB
描述
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.輸入
The input consists of T test cases. The number of test cases ) (T is given in the first line of the input file. 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 3 + N -rd
line, the remaining test cases are listed in the same manner as above.
輸出
The output should contain the minimum time in minutes to complete the moving, one per line.
樣例輸入
3
4
10 20
30 40
50 60
70 80
2
1 3
2 200
3
10 100
20 80
30 50
樣例輸出
10
20
30
轉載于:https://www.cnblogs.com/zhuyuanhao/archive/2012/10/03/3262880.html
總結
以上是生活随笔為你收集整理的POJ1083 Moving Tables的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 农忙……
- 下一篇: 国庆七天乐 Day5