HDU1051

Wooden Sticks

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

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).

 

有一堆n个木棍。每个棒的长度和重量是预先知道的。木棒要用木工机械逐一加工。它需要一些时间,称为设置时间,机器准备加工一根棍子。安装时间与清洗操作和更换机器中的工具和形状有关。木工机床的安装时间如下:

(a)第一根木棍的安装时间为1分钟。

(b)在加工长度l和重量w的棒材之后,如果l<=l'和w<=w',机器将不需要长度l'和重量w'的棒材的安装时间。否则,安装需要1分钟。

你要找到最小的设置时间来处理给定的一堆木棒。例如,如果有5根棍子的长度和重量对(4,9)、(5,2)、(2,1)、(3,5)和(1,4),那么最小设置时间应该是2分钟,因为存在一系列对(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

 

基本思路:可以将点放在坐标系中观察,将读入的坐标按照坐标排序,排序规则为按照X优先再比较Y,让点符合坐标系特点。

向X轴正方向看,从第一个点(Xi,Yi)开始,观察下一个点(X(i+1),Y(i+1))满足情况,若满足,则从该满足的点(X(i+1),Y(i+1))继续与该点的下一个(X(i+2),Y(i+2))比较,否则选定的第一个点(Xi,Yi)继续与点(X(i+2),Y(i+2))比较并且记录当前位置作为下次搜索的起点,到末尾时便说明没有更大符合条件的,时间+1,并更新下次搜索的起点

例如:

对于题目例子中的(4,9)、(5,2)、(2,1)、(3,5)和(1,4),经过排序后得到的是(1,4)、(2,1),(3,5),(4,9),(5,2)

首先从(1,4)开始向右搜索,发现(2,1)未被计算过,但是不满足情况,那么将该位置记为start(每次搜索前被赋值为n(坐标点的个数)),作为下次搜索的起点,继续向右发现(3,5)满足情况,那么重新将(3,5)作为与下一个比较的点并且标记为已计算,与(4,9)比较,满足情况,则(4,9)与(5,2)比较发现不满足情况,但是已到达尾部,开始下一次搜索,开始位置为start,即(2,1),由于(3,5),(4,9)已经被标记为计算过,将与(5,2)进行匹配,成功,标记为已计算,没有发现匹配不成功的情况,故start位置为n,下次匹配不会进行,即完成全部计算

代码如下

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

typedef struct
{
    int x,y;                                     //坐标
    int flag;                                    //是否已经被计算的标志,
}lw;

int T,n;                                         //T表示测试次数,n表示一次测试中的数据数
lw a[5001];

inline bool check(lw& a, lw& b)                  //判断是否满足
{
    return a.y<=b.y;
}

inline bool cmp(lw& a,lw& b)                     //排序,按照先比X后比Y
{
    if(a.x==b.x)
        return a.y<=b.y;
    else
        return a.x<b.x;
}

int main()
{
    cin>>T;
    while(T--)
    {
        int start,startflag;                     //start表示当一次搜索完成时下次搜索开始的地方,startflag作为对start进行改变的条件
        cin>>n;
        for(int i=0;i<n;i++)                     //读入数据
        {
            cin>>a[i].x>>a[i].y;
            a[i].flag=0;
        }
        sort(a,a+n,cmp);                         //排序
        int len=0,i=0;
        while(i<n)
        {
            startflag=1;                         //为1时说明没有记录,为0说明已经记录不用再次记录
            start=n;                             //当一次搜索时全部匹配成功,说明匹配完成,不用继续
            for(int j=i+1;j<n;j++)
            {
                if(!a[j].flag)                   //当前点没有被计算过
                {
                    if(check(a[i],a[j]))         //满足条件
                    {
                        i=j;
                        a[j].flag=1;             //标记已被计算过
                    }
                    else if(startflag)           //不满足情况的点,则下次从该点开始
                    {
                        start=j;
                        startflag=0;             //标记,说明下次搜索的起点已经确定,不用再次改变
                    }
                }
            }
            i=start;                             //改变下次搜索的起点
            len++;                               //时间加1
        }
        cout<<len<<endl;
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值