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