您的位置:首页 > 其它

POJ 1065 Wooden Sticks(zoj 1025) 最长单调子序列

2013-11-12 23:20 579 查看
POJ :http://poj.org/problem?id=1065

ZOJ: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=25

看大神的代码的研究的。。。

心情不好该学习还是要学习的。。。。QAQ

其实题目的意思就是把所有元素分为最少的堆数,每堆有l<=l' and w<=w' 按l排序后(l相等则按w),问题转化为把所有元素分为最少的堆数,每堆有w<=w'(l<=l' 显然成立) 即已知一个数列,要求最少用多少个不下降序列完全覆盖

可以证明不下降序列完全覆盖数就是最长下降子列的长度(记为L): 显然覆盖数不能比L小,否则由抽屉原理,必然有下降子列中两元素(a < b)在同一不下降须列中(a <= b),这是不可能的 由覆盖数可以取得L,而序列的每个元素在不同堆中,然后每次将元素“贪心”地分在堆中,这个过程和dp地求最长下降子列很像,可以构造解,也可以反证如果不能分号,与下降子列长度为L矛盾。

于是先将数列按照l,w的顺序进行快排,然后在求出w序列中的最长递减序列的长度就可以了.(摘自http://blog.csdn.net/wmbol/article/details/5450952

那么就转化为求最长递减序列的长度。

和LIS(最长上升字串差不多)

也可以二分来做。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=5000+10;
struct data
{
int weight;
int length;
}a[MAXN];

bool operator <(const data &a,const data &b)
{
if(a.length == b.length)
return a.weight < b.weight;

return a.length < b.length;
}

int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int dp[MAXN];
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d%d",&a[i].length,&a[i].weight);

sort(a,a+n);

dp[0]=1;
int maxl;
for(int i=1;i<n;i++)
{
maxl=1;
for(int j=i;j>=0;j--)
{
if(a[i].weight < a[j].weight && dp[j]+1 > maxl)
{
maxl= dp[j]+1;
}
}
dp[i]=maxl;
}

int ans=0;
for(int i=0;i<n;i++)
if(dp[i]>ans)
ans=dp[i];

printf("%d\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: