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

原文地址:https://www.cnblogs.com/TenosDoIt/p/3031727.html