ZOJ 1025 Wooden Sticks (DP)

题目地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1025

如果我们定义在一个sticks序列中,对所有的 j>i 均满足 :  sticks[i].l>=sticks[j].l 且 sticks[i].w>=sticks[j].w  ,则称这个序列为一个 “簇”。本题就是求把所有的元素分为最少的簇数。

假设输入为A,首先把A排序(按 l 的增序,若两个元素的 l 相同,则按 w 的增序),排序后的序列称为B,对序列B按照元素的属性 w 求最长递减子序列的长度(严格递减),记为len。则我们要求得最少簇数就等于 len 。

最长递减子序列的动态规划方法详见我的另一篇博客:http://www.cnblogs.com/TenosDoIt/archive/2013/04/19/3031589.html

下面我们证明最少簇数 cu 等于 len:

将最长递减子序列记为C,则C中的元素满足C[i].l>=C[j].l && C[i].w<C[j].w ( 其中 i<j ),他们不满足簇的性质。因此最长递减子序列中的len个元素必定每个都分布在不同的簇中,因此最少的簇数为len。

代码如下:

 1 #include<iostream>

 2 #include <vector>

 3 #include <algorithm>

 4 using namespace std;

 5 

 6 struct node

 7 {

 8     int l;

 9     int w;

10 };

11 

12 bool comp(struct node a,struct node b)

13 {

14     if(a.l==b.l)

15         return a.w<b.w;

16     else return a.l<b.l;

17 }

18 

19 

20 int main()

21 {

22     int caseNum;

23     cin>>caseNum;

24     while(caseNum--)

25     {

26         int N;

27         vector<node> sticks;

28         cin>>N;

29         for(int i=1;i<=N;++i)

30         {

31             node tmp;

32             cin>>tmp.l>>tmp.w;

33             sticks.push_back(tmp);

34         }

35         sort(sticks.begin(),sticks.end(),comp);

36 

37         int *F=new int[N+1];

38         int result=0;

39         F[0]=1;

40         for(int i=1;i<N;i++)

41         {

42             F[i]=1;

43             for(int j=0;j<i;j++)

44             {

45                 if(sticks[i].w<sticks[j].w)

46                     F[i]=max(F[i],F[j]+1);

47             }

48             

49             if(F[i]>result)

50                 result=F[i];  

51         }

52         delete []F;

53         cout<<result<<endl;

54     }

55     return 0;

56 }

 【版权声明】转载请注明出处 http://www.cnblogs.com/TenosDoIt/archive/2013/04/19/3031727.html

你可能感兴趣的:(ZOJ)