hdu acm 1051 贪心,排序,dilworth定理,最长递减序列长度

来源:互联网 发布:mac打开终端快捷键 编辑:程序博客网 时间:2024/05/18 11:48

dilworth 定理: 最小链划分数  =  最大反链的长度。

于是先按照l 或者 w 排序, 再求最大递减子序列的长度即可~  

要注意,第一次按照 l 排序时(按w 思路也一样),如果出现l相同的情况, 那么应该再在l相同的木头之间比较w, 并且把w最小的木头放在前面。 

如: ( l , w )  = (5,3)  (5,2 ) (5, 1)  则要排成 (5,1) (5,2) (5,3)。

#include<iostream>using namespace std;int l[5002];int w[5002];int ln[5002];int T;inline void swap_(int &a, int &b){int tmp;tmp = a;a = b;b = tmp;}void fast_sort(int top, int bot){if(top < bot){int j = top;for(int i = top ; i < bot ; i ++){if(l[i] < l[bot]){swap_(l[i],l[j]);swap_(w[i],w[j]);j++;}else if(l[i]==l[bot] && w[i]<w[bot]){swap_(w[i],w[bot]);}}swap_(l[j],l[bot]);swap_(w[j],w[bot]);fast_sort(top,j-1);fast_sort(j+1,bot);}}int ln_len(const int &n_){int len = 0;for(int i = 0 ; i < n_ ; i++){int top = 1;int bot = len;int mid;while(top <= bot){mid = (top+bot)/2;if( ln[mid] > w[i])top = mid+1;else bot = mid-1;}ln[top] = w[i];if(top > len)len++;}return len;}int main(){int n,res;ln[0] = 10001;scanf("%d",&T);while(T){scanf("%d",&n);for(int i = 0 ; i < n ; i++)scanf("%d%d",&l[i],&w[i]);fast_sort(0,n-1);res = ln_len(n);printf("%d\n",res);T--;}return 0;}


0 0