ZOJ_Wooden Sticks

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1025

题意:给定一些stick,有一定长度和重量,现在 需要用最少的分组,实现任意一组中stick的长度和重量都不降 。

算法: DP+最长下降子序列(或贪心)。

分析:虽然是二维的比较,但是排个序就可以变二维的为一维的,可以证明最少不降序列覆盖数等于最长下降子序列的长度。

DP代码:

/*
  Name:	ZOJ_1025
  Algorithm: DP+ 最长XX子序列	
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

#define MAX 5001
#define max(a,b) (a>b?a:b)
using namespace std;

int T,n;
int dp[MAX] ;

struct Node{
	int l,w;
	friend bool operator < (const Node& a,const Node& b)
	{
		if(a.l == b.l)	return a.w < b.w ;
		else 	return a.l < b.l ;	
	}	
}stick[MAX] ;

int main()
{
    //freopen("1in.txt","r",stdin);
    //freopen("1out.txt","w",stdout);
	scanf("%d",&T);
	int cnt ;
	while(T--)
	{
		scanf("%d",&n);
		
		for(int i=0;i<n;i++)
		{
			scanf("%d %d",&stick[i].l , &stick[i].w);	
		}	
		sort(stick,stick+n);
		memset(dp,0,sizeof(dp));
		dp[0] = 1 ;
		int MAX_ = dp[0] ;
		for(int i=1;i<n;i++)
		{
			int max_ = 1;
			for(int j=0;j<i;j++)
			{
				if(stick[j].w > stick[i].w)
				{
					max_ = max(max_,dp[j]+1) ;	
				}
			}	
			dp[i] = max_ ;
			MAX_ = max(MAX_,dp[i]) ;
		}
		printf("%d\n",MAX_);
	}

    return 0;
}


思路二:贪心。

本题类似于导弹拦截,只是这里是二维的,用上面的排序方面可以将二维的比较转化为一维的比较,因此可以用类似于导弹拦截的贪心思想。

贪心代码:

/*
  Name:	ZOJ_1025
  Algorithm: 贪心	
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

#define MAX 5001
#define max(a,b) (a>b?a:b)
using namespace std;

int T,n;
int max_len[MAX];

struct Node{
	int l,w;
	friend bool operator < (const Node& a,const Node& b)
	{
		if(a.l == b.l)	return a.w < b.w ;
		else 	return a.l < b.l ;	
	}	
}stick[MAX] ;

int main()
{
    //freopen("1in.txt","r",stdin);
    //freopen("1out.txt","w",stdout);
	scanf("%d",&T);
	int cnt ;
	while(T--)
	{
		scanf("%d",&n);
		
		for(int i=0;i<n;i++)
		{
			scanf("%d %d",&stick[i].l , &stick[i].w);	
		}	
		sort(stick,stick+n);
		cnt = 1;
		max_len[1] = stick[0].w;
		for(int i=1;i<n;i++)
		{
			int max_ = -1,max_n; 			
			for(int j=1;j<=cnt;j++)
			{
				if(stick[i].w >= max_len[j])
				{
					if(max_ < max_len[j])                //每次贪心加载长度最长的后面
					{
						max_ = max_len[j] ;
						max_n = j ;	
					}
				}	
			}	
			if(max_ == -1)                                  //此stick不能加在其他的后面,需要加一次时间
			{
				cnt ++ ;
				max_len[cnt] = stick[i].w ;	
			}
			else{
				max_len[max_n] = stick[i].w ;	
			}
		}
		printf("%d\n",cnt);
	}

    return 0;
}





你可能感兴趣的:(ZOJ_Wooden Sticks)