1050 Moving Tables 贪心算法

来源:互联网 发布:360软件管理专家 编辑:程序博客网 时间:2024/05/19 16:51

Moving Tables

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 12304    Accepted Submission(s): 4226


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.
 

Input
The 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.
 

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
102030

参考文章:http://blog.csdn.net/code_pang/article/details/8251240

#include <stdio.h>#include "stdlib.h"/* 题目的意思是给你一连串的要移动的房间组,由于会出现道路同时使用的情况,则会出现时间增加。 为了找到时间最少的移动方案,我们需要做的是利用贪心算法,找到最优解。 思路如下: 1、首先我们进行优化,会发现偶数2和奇数1占用的道路是一样的,则我们将移动的房间进行优化,全部变成奇数 比如从1移动到6则相当于从1移动到5,则把房间组(1、6)改成(1、5)。 2、然后进行排序,按照起始房间,从小到大排序。 3、然后通过比较下一个的房间的起点和现在的终点是否重合,重合的话则会同时占用,不考虑,    若不是则将其放在同个时间段,设置为考虑过了。一直找到最后。 4、第一次遍历完成后,假如没有全部移动都放入,则再继续从头开始,找到第一个还未被考虑过的要移动的房间组 然后重复上述步骤。 5、以上为贪心算法的思想。 (提供两种方法,具体如下:)*///由于速度的关系,这一题使用快速排序进行//普通的排序应该也可以,看具体数据void swap(int *x,int *y){    int temp;    temp = *x;    *x = *y;    *y = temp;}int choose_pivot(int i,int j ){    return((i+j) /2);}void quicksort(int list[],int end[],int m,int n){    int key,i,j,k;    if( m < n)    {        k = choose_pivot(m,n);        swap(&list[m],&list[k]);        swap(&end[m],&end[k]);        key = list[m];        i = m+1;        j = n;        while(i <= j)        {            while((i <= n) && (list[i] <= key))                i++;            while((j >= m) && (list[j] > key))                j--;            if( i < j){                swap(&list[i],&list[j]);                swap(&end[i],&end[j]);            }        }        // 交换两个元素的位置        swap(&list[m],&list[j]);        swap(&end[m],&end[j]);        // 递归地对较小的数据序列进行排序        quicksort(list,end,m,j-1);        quicksort(list,end,j+1,n);    }}//以上为快排部分/* //这个方法可能会超时间 void sort_start(int start[],int end[],int n){//按照起始位置从小到大排序  for(int i=0;i<n;i++) for(int j=0;j<n-i;j++){ if(start[j]>start[j+1]){ int temp=start[j+1]; start[j+1]=start[j]; start[j]=temp; temp=end[j+1]; end[i+1]=end[j]; end[j]=temp; //flag不用变,因为全部都没搬动 } } } */int main(){        freopen("/Users/qigelaodadehongxiaodi/Desktop/data1.txt", "r", stdin);    //这个不理,是用来方便输入输出的东西,利用文本输入流来读取数据    //提交代码的时候记得注销这条语句        int t;    int n;    int start[100],end[100],flag[100];    scanf("%d",&t);        while(t>0){        scanf("%d",&n);        for(int i=0;i<n;i++){            scanf("%d %d",&start[i],&end[i]);            if(start[i]>end[i]){//注意加上这个判断,可能为从房间6移动到房间1                int temp=end[i];                end[i]=start[i];                start[i]=temp;            }                        start[i]=start[i]+start[i]%2-1;//注意加减号不要打成中文的+-,而应该是+-            end[i]=end[i]+end[i]%2-1;            flag[i]=1;//表示没搬动            //减去的的原因是:上下对应,会占用位置,因此只需要判断其奇数部分,偶数减1,奇数不变            //因为1和2其实占用一个通道,则把到2当成到1即可,所以让偶数减1,使2变成了1。        }                //sort_start(start,end,n);//按照起始位置排序                quicksort(start,end,0,n-1);//按照起始位置排序                int cnt=0;//用来记录是否所有房间的都搬完了        int total_time=0;//总用时                while(cnt!=n){            int i=0,left;            while(flag[i]==0){                i++;            }//直到找到位置最小没搬过的房间                        left=end[i];//表示一段长度的后面部分            flag[i]=0;//表示这一个房间(段)搬过了            cnt++;//表示已经判断了多少了房间                        for(int j=i;j<n-1;j++){                if((left<start[j+1])&&flag[j+1]==1){//如果下一段可以在这个十分钟内同时进行                    left=end[j+1];                    flag[j+1]=0;                    cnt++;                }            }                        //直到把这一次的10分钟期间的所有找到            total_time+=10;        }                printf("%d\n",total_time);        t--;    }    return 0;}/*_____________________________________________________________________________*/#include <stdio.h>#include <string.h>#define SIZE 405/* 这个的思路与上一个不同,这个是假如时间重合,则进行叠加,叠加到的最大项就是所需时间的最大值 */int main(void){            freopen("/Users/qigelaodadehongxiaodi/Desktop/data1.txt", "r", stdin);    //这个不理,是用来方便输入输出的东西,利用文本输入流来读取数据    //提交代码的时候记得注销这条语句        int count[SIZE];    int i, j, testNum, n, max, from, to;        scanf("%d", &testNum);    while (testNum-- != 0)    {        scanf("%d", &n);        memset(count, 0, sizeof(count));        for (i = 0; i < n; i++)        {            scanf("%d %d", &from, &to);            if (from > to)            {                int temp = from;                from = to;                to = temp;            }            if (from % 2 == 0)            {                count[from-1]++;            }            if (to % 2 == 1)            {                count[to+1]++;            }            for (j = from; j <= to; j++)            {                count[j]++;            }        }        max = 0;                        for (i = 0; i < SIZE; i++)        {            if (count[i] > max)            {                max = count[i];            }        }                        printf("%d\n", max*10);    }    return 0;}

0 0