1050 Moving Tables 貪心算法

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
10 20 30

參考文章: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;
}







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章