问题描述
现有n根木棒,已知它们的长度和重量,要用一部木工机一根一根地加工这些木棒。该机器在加工过程中需要一定的准备时间,是用于清洗机器,调整工具和模板的。木工机需要的准备时间如下:
(1)第一根木棒需要1分钟的准备时间。
(2)在加工完一根长为length,重为weight的木棒之后,接着加工一根长为length’(length’<=length),重为weight’(weight<=weight’)的木棒是不需要任何准备时间的。否则需要一分钟的准备时间。
本题的要求是:
给定n(1<=n<=5000)根木棒,已知它们的长度和重量,请编写程序:找到加工完所有的木棒所需要的最少准备时间,以及加工这些木棒的顺序。
解题思路
先对n根木棒按照长度进行全局排序,得到了一个长度有序而重量无序的序列(贪心先按长度排序)。
再在每一个同一长度序列中,对重量进行局部排序。至此,长度和重量都是有序的。
最长单调递增子序列的个数(采用动态规划),即为最终的答案。
代码如下
#include<bits/stdc++.h>
#define maxN 5001
using namespace std;
struct stick
{
int l;
int w;
};
bool cmp(stick a,stick b)
{
if(a.l==b.l)
return a.w<b.w;
else if(a.l<b.l)
return true;
else
return false;
}
int LIS(int n,stick a[])
{
int b[maxN];
int k;
memset(b,0,sizeof(b));
b[0]=1;
for(int i=0;i<n;i++)
{
k=0;
for(int j=0;j<i;j++)
{
if(a[i].w<a[j].w&&k<b[j])
k=b[j];
b[i]=k+1;
}
int max=0;
for(int i=0;i<n;i++)
if(b[i]>max)
max=b[i];
return max;
}
}
int main()
{
int n,x;
cin>>n;
stick data[maxN];
for(int i=0;i<n;i++)
{
cin>>x;
stick data[x];
for(int j=0;j<x;j++)
{
cin>>data[j].l>>data[j].w;
}
}
sort(data,data+n,cmp);
cout<<LIS(n,data)<<endl;
}