贪心算法——Wooden Sticks

 


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
 
题目要求,给出包含两个关键字的一个序列,最少能够组成多少个两个关键字都为升序的序列。

/*****************************************************************************************************************************************************************************************************

简单的贪心算法问题,由于刚刚接触到贪心算法,对他的本质不够了解。虽然自己写的代码提交后也过掉了,但是看到题解后还是感觉受益匪浅。我写的算法比较容易理解,大家可以参考。后面的贪心 算法,应该是本题的正解。

贪心的基本思路是::首先对两个关键字进行排序。然后第一重 i 循环遍历所有点,如果遇到没有被标记过的点(用 s 数组进行标记),进入第二重循环,比较第二关键字,在保持升序的状态下尽可能多的标记带点。这样进入了几次第二重循环就需要多少时间。

我的思路::首先对两个关键字进行排序。第一重 i 循环遍历所有的点,第二重 j 循环遍历s数组并把 i 的第二个关键字(设为se)计入到 s数组中,(记录的原理是,如果se大于s 数组中的值,就把该值改成se)。这样s中有几个不为0的值,就要花多长时间。

*****************************************************************************************************************************************************************************************************/

首先是我的代码::

#include <iostream>
#include <sstream>
#include <ios>
#include <iomanip>
#include <functional>
#include <algorithm>
#include <vector>
#include <string>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <climits>
#include <cctype>
using namespace std;
#define XINF INT_MAX
#define INF 0x3F3F3F3F
#define MP(X,Y) make_pair(X,Y)
#define PB(X) push_back(X)
#define REP(X,N) for(int X=0;X<N;X++)
#define REP2(X,L,R) for(int X=L;X<=R;X++)
#define DEP(X,R,L) for(int X=R;X>=L;X--)
#define CLR(A,X) memset(A,X,sizeof(A))
#define IT iterator
typedef long long ll;
typedef pair<int,int> PII;
typedef vector<PII> VII;
typedef vector<int> VI;
//const int MAXN = 10010;
//#define INF 0x3FFFFFFF
/*************************************
 **************头文件*****************
 *************************************/
vector<pair<int,int> > a;//利用vector便于排序
int s[5002];//作用见思路分析
int main()
{
	int T;
	cin>>T;
	while(T--){
		int n;
		cin>>n;
		int l,w;
		a.clear();
		REP(i,n){
			cin>>l>>w;
			a.PB(MP(l,w));
		}
		memset(s,0,sizeof(s));			//初始化s
		sort(a.begin(),a.end());		//进行排序	
		REP(i,n)						//遍历每一个点
			REP(j,n){					//遍历s数组
				if(a[i].second>=s[j]){	
					s[j] = a[i].second;
					break;				//当把a[i].second放进数组后就直接break,避免重复操作
				}
			}
		int t = 0;
		REP(i,n)
		if(s[i] != 0)					//当不为0时,必然有a[i].second放到s中
			t++;
		else break;						//当为0时,不然没有a[i].second放到s中,后面的也不会再有
		cout<<t<<endl;
	}
	return 0;
}


 下面是通过学习贪心算法写出来的代码

#include <iostream>
#include <sstream>
#include <ios>
#include <iomanip>
#include <functional>
#include <algorithm>
#include <vector>
#include <string>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <climits>
#include <cctype>
using namespace std;
#define XINF INT_MAX
#define INF 0x3F3F3F3F
#define MP(X,Y) make_pair(X,Y)
#define PB(X) push_back(X)
#define REP(X,N) for(int X=0;X<N;X++)
#define REP2(X,L,R) for(int X=L;X<=R;X++)
#define DEP(X,R,L) for(int X=R;X>=L;X--)
#define CLR(A,X) memset(A,X,sizeof(A))
#define IT iterator
typedef long long ll;
typedef pair<int,int> PII;
typedef vector<PII> VII;
typedef vector<int> VI;
//const int MAXN = 10010;
//#define INF 0x3FFFFFFF
/*************************************
 **************头文件*****************
 *************************************/
vector<pair<int,int> > a;//利用vector便于排序
int s[5002];//作用见思路分析
int main()
{
	int T;
	cin>>T;
	while(T--){
		int n;
		cin>>n;
		int l,w;
		a.clear();
		REP(i,n){
			cin>>l>>w;
			a.PB(MP(l,w));
		}
		memset(s,0,sizeof(s));			//初始化s
		sort(a.begin(),a.end());		//进行排序	
		int ans = 0;					//记录结果
		REP(i,n)
		{
			if(s[i])continue;			//如果i被访问过,不再进入二重遍历
			s[i] = 1;					//没有被访问过的,标记为访问过,并进入二重遍历
			int W = a[i].second;		//记录第二关键字,便于比较
			REP2(j,i,n-1)				//i之前的点肯定已经被访问过,无需在进行比较
			{
				if(!s[j]&&a[j].second>=W)//没有被访问,并且第二关键字升序
				{
					s[j] = 1;			//标记为已经访问
					W = a[j].second;	//下次循环时,比较这一次的se,保持升序
				}
			}
			ans++;						//进入第二重循环就会累加一次
			
		}
		cout<<ans<<endl;				
		
	}
	return 0;
}
 


 

 

你可能感兴趣的:(贪心算法,Sticks,Wooden,多关键字排序)