POJ1083贪心算法

POJ1083贪心算法

题目

Description

The famous ACM (Advanced Computer Maker) Company has rented a floor of a building whose shape is in the following figure.
POJ1083贪心算法_第1张图片

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.
POJ1083贪心算法_第2张图片

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.

Input

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.

Output

The output should contain the minimum time in minutes to complete the moving, one per line.

Sample Input

3
4
10 20
30 40
50 60
70 80
2
1 3
2 200
3
10 100
20 80
30 50

Sample Output

10
20
30

解题思路

计数法

对应走廊的每一段长建立相应的数组元素,总共200个。移动桌子时每经过一次某一段的走廊,该段走廊的计数就增1,最后取计数最大的一段,乘以时间即可。重复经过最多次的就是结果。注意1和2对应同一段,3和4对应同一段。这里采取下一种贪心算法。

贪心算法

每一个要移动的桌子的起始和终止位置分别为s、f,且s

注意几个坑

首先就是房间的布局产生的坑:奇数房间在上方,偶数房间在下方,正对的房间号共用一段走廊。这里有两种情况:上一次移动的桌子终点为偶数,则下一个可同时移动的桌子起点必须比这个偶数大;若上一次移动的桌子终点为奇数,由于该奇数+1得到其正对面的偶数房间,共享一段走廊,故下一个可同时移动的桌子的起点必须比该奇数+1大。

然后是贪心算法初始排序的坑:如果按照终点位置升序排序,那么每一次可以得到局部最优,但最终的时间结果不是最优,这是个大坑,部分数据过不了,例如如下一组输入:

1
4
2 4
1 6
10 12
5 14

该组数据如果按照终点升序得到结果为30,如果按照起点升序得到结果为20。

为什么必须按照起点升序进行贪心

待解答

代码如下

#include
//贪心算法,按开始s升序排序可以得到全局最优
struct Move{
     
    int s;//开始,s
    int f;//结束
    bool moved;//是否搬动完成
}Table[201];
void QuickSort(struct Move Table[],int i,int j){
     
    if(j<=i)	return;
    struct Move pivort=Table[i];
    int low=i,high=j;
    while(low<high){
     
        while(Table[high].s>=pivort.s&&high>low){
     
            high--;
        }
        Table[low]=Table[high];
        while(Table[low].s<=pivort.s&&high>low){
     
            low++;
        }
        Table[high]=Table[low];
    }
    Table[high]=pivort;
    QuickSort(Table,i,high);
    QuickSort(Table,high+1,j);
}
int main(){
     
    int T,N,i,j,count,m,time,a,b;
    scanf("%d",&T);
    for(i=1;i<=T;++i){
     
        scanf("%d",&N);
        for(j=1;j<=N;++j){
     
            scanf("%d%d",&a,&b);
            Table[j].s=a<b?a:b;//开始<完成,贪心前提
            Table[j].f=a>b?a:b;
            Table[j].moved=false;
        }
        QuickSort(Table,1,N);
        for(count=0,time=0;count<N;){
     
            for(j=1;j<=N;++j){
     
                if(!Table[j].moved){
     
                    m=j;//寻找第一个没被移动的,并且移动
                    Table[j].moved=true;
                    count++;
                    break;
                }
            }
            for(j=m+1;j<=N;++j){
     
                if(!Table[j].moved){
     
                    if((Table[m].f%2&&Table[j].s>(Table[m].f+1))||((Table[m].f%2==0)&&Table[j].s>Table[m].f)){
     //巨大的坑
                        m=j;
                        Table[j].moved=true;
                        count++;
                    }
                }
            }
            time+=10;//一次可同时移动的最大集合选取完成
        }
        printf("%d\n",time);
    }
    return 0;
}

你可能感兴趣的:(贪心算法,快速排序,算法)