HDU 1051 Wooden Sticks

一、题目概述

Wooden Sticks

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


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
 

 

Source
 

二、题目释义

给你一堆具有长度和重量的木头,让你去机器里加工,机器会有一个一分钟的set时间,首次加工需要set一次,当连续放入的木头不满足后者的长度和重量都大于等于前者时,机器需要set一下,让你求出最短的set时间(不用求出序列)

三、思路分析

我们会非常直观的想到从小到大进行排序,但很遗憾,长度和重量我们都必须考虑,我们无法对两个主元进行排序操作,但是要让机器set时间最短,其必然要满足某一个元素如长度是从小到大排序的,这是最优解的必要条件,那我们便可以对长度进行排序,对重量进行贪心。

确定使用贪心策略,最关键的有两步,一步即设计贪心策略,二即证明由贪心得到的局部最优解最优解即为整体最优解

贪心策略:排序之后扫描一遍stick,将满足条件的stick标记为vis[i] = 1,即已经被使用,不满足条件的stick为未使用,(需要注意的是当遇到不满足的stick时,扫描比较应当是比较不符合前一个与不符合后一个)扫描到尾部之后,再从第一个未使用的stick开始,扫描一遍全部未使用的stick重复之前的操作,直到全部stick都被使用,每扫描一次计数+1

证明:贪心策略所得到为每一次尽可能大的子串,每次对子串取尽可能大,所得到即为最少的子串个数

四、AC代码

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 using namespace std;
 6 
 7 const int N = 5005;
 8 struct stick
 9 {
10     int len,wei;
11 }a[N];
12 
13 int vis[N];
14 
15 bool cmp(stick a, stick b)
16 {
17     if(a.len == b.len)
18         return a.wei < b.wei;
19     else return a.len < b.len;
20 }
21 
22 int main()
23 {
24     int T,n; cin >> T;
25     int flag;
26     while(T--)
27     {
28         cin >> n;
29         memset(vis,0,sizeof(vis));
30         for(int i=0; i<n; i++)
31             scanf("%d%d",&a[i].len,&a[i].wei);
32         sort(a,a+n,cmp);
33         for(int i=0; i<n; i++)
34         {
35             printf("%d %d ",a[i].len,a[i].wei);
36         }
37         cout << endl;
38         int st=0, cnt=0;
39         vis[0] = 1;
40         while(st<n)
41         {
42             cnt++; flag = 1;
43             for(int j=st,i=st+1; i<n; i++)
44             {
45                 if(vis[i]) continue;
46                 if(a[j].wei<=a[i].wei)
47                 {
48                     vis[i] = 1;
49                     j = i; // 这一步实现,只有符合了条件,比较的stick才会依次向前迭代
50                 }
51                 else
52                 {
53                     if(flag) // 这里的flag用来确定只有在这一遍扫描中,只有第一个未使用的会被标记st,以作为下一次的起点
54                     {
55                         st = i;
56                         flag = 0;
57                     }
58                 }
59             }
60             if(flag) break;
61         }
62         cout << cnt << endl;
63     }
64     return 0;
65 }

 

posted @ 2018-01-22 09:00  Nevercome  阅读(742)  评论(0编辑  收藏  举报