1. 程式人生 > >1051 Wooden Sticks

1051 Wooden Sticks

Wooden Sticks

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


Problem Description There is a pile of n wooden sticks. The length and weight of each stick are known in advance. The sticks are to be processed by a woodworking machine in one by one fashion. It needs some time, called setup time, for the machine to prepare processing a stick. The setup times are associated with cleaning operations and changing tools and shapes in the machine. The setup times of the woodworking machine are given as follows:

(a) The setup time for the first wooden stick is 1 minute.
(b) Right after processing a stick of length l and weight w , the machine will need no setup time for a stick of length l' and weight w' if l<=l' and w<=w'. Otherwise, it will need 1 minute for setup.

You are to find the minimum setup time to process a given pile of n wooden sticks. For example, if you have five sticks whose pairs of length and weight are (4,9), (5,2), (2,1), (3,5), and (1,4), then the minimum setup time should be 2 minutes since there is a sequence of pairs (1,4), (3,5), (4,9), (2,1), (5,2).

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 consists of two lines: The first line has an integer n , 1<=n<=5000, that represents the number of wooden sticks in the test case, and the second line contains n 2 positive integers l1, w1, l2, w2, ..., ln, wn, each of magnitude at most 10000 , where li and wi are the length and weight of the i th wooden stick, respectively. The 2n integers are delimited by one or more spaces.
  Output The output should contain the minimum setup time in minutes, one per line. Sample Input 3 5 4 9 5 2 2 1 3 5 1 4 3 2 2 1 1 2 2 3 1 3 2 2 3 1
Sample Output 2 1 3
#include <stdio.h>
#include "stdlib.h"

/*
 題目的意思是將一系列的(length,weight)進行分組,使得每一組都成序列,
 使每組中的length和weight都遞增。
 本題思路:
 1、首先將所有的數進行排序,如果長度相等就按照重量排,從小到大
 2、從第一個開始,找出能和第一個放在一個集合的數
   比如(4,9), (5,2), (2,1), (3,5),(1,4),
 拍完序的結果是(1 4)(2 1)(3 5)(4 9)(5 2),
 (1 4)(3 5)(4 9),這可以在一個集合,則總集合數加1,
 然後再從頭繼續找,找到第一個沒被加入過的,就找到了(2,1),
 然後發現剩下兩個都是一個組合,則一共有2組,則需要設定時間兩次,
 輸出為2.
 3、貪心演算法的思路就是如此,每次從頭開始找第一個未被加入集合的項,
 用貪心找到所有滿足這個集合的。
 */

typedef struct{
    
    int length;
    int weight;
}STICK;

void sort_stick(STICK stick[],int n){
    
    for(int i=0;i<n;i++)
        for(int j=i;j<n;j++){//注意是i不是1
        if(stick[i].length>stick[j].length||
           (stick[i].length==stick[j].length&&
            stick[i].weight>stick[j].weight)){
               int temp=stick[i].length;
               stick[i].length=stick[j].length;
               stick[j].length=temp;
               temp=stick[i].weight;
               stick[i].weight=stick[j].weight;
               stick[j].weight=temp;
        }
    }
}
int main()
{
   
    freopen("/Users/qigelaodadehongxiaodi/Desktop/data1.txt", "r", stdin);
    //這個不理,是用來方便輸入輸出的東西,利用文字輸入流來讀取資料
    //提交程式碼的時候記得登出這條語句
    
    
    STICK stick[6000];
    int flag[6000]={0};//注意陣列大小
    int n,t;
    scanf("%d",&t);
    
    while(t>0){
        scanf("%d",&n);
        for(int i=0;i<n;i++){
            scanf("%d %d ",&stick[i].length,&stick[i].weight);
            flag[i]=1;
        }
        
        sort_stick(stick, n);//按照思路中的2排序
        
        int cnt=0,cntnum=0;
        int total=0;
        int last_length=0,last_weight=0;
        //last_兩個代表則上一個,比如(1 4)(2 1)(3 5)(4 9)(5 2)
        //找到(1,4),然後變成last_length=1,lats_weight=4
        //下一個找到了(3 5),然後就變成了3、5.
        while(cnt<n){
            
            while(last_length==0&&last_weight==0){
                if(flag[cntnum]!=0){
                    last_length=stick[cntnum].length;
                    last_weight=stick[cntnum].weight;
                    flag[cntnum]=0;
                    cnt++;
                            }
                cntnum++;
            }//這個部分就是沒有集合或者上一個集合已經找完全了,開始找下一個集合
            //所以會發現last_length、last_weight都是0
            
            if(stick[cntnum].length>=last_length&&stick[cntnum].weight>=last_weight&&flag[cntnum]==1){
                flag[cntnum]=0;
                last_length=stick[cntnum].length;
                last_weight=stick[cntnum].weight;
                cntnum++;
                cnt++;
            }else{
                
                cntnum++;
            }
            //這部分則是不斷的遍歷全部,然後把符合條件的放在一個集合
            //cnt代表總的被放入的數
            //cntnum代表現階段遍歷到的數的下標誌
            if(cnt==n){
                total++;
                break;
            }//如果最後一個數字都放入了,即cnt==n,我們讓總數加1,然後退出
            //加入不設定這個退出機制,在樣例的第三個鍾會少1,
            //因為其有三個集合,第三個會在原序列末尾
            if(cntnum==n){
                cntnum=0;
                last_length=0;
                last_weight=0;
                total++;
            }
            //如果所有都遍歷完了,則繼續從頭開始遍歷,
            //即思路中2的思想
        }
        
        printf("%d\n",total);
        
        t--;
    }
    return 0;
}