zoj 1025 Wooden Sticks (DP子序列)(第100,纪念一下)

来源:互联网 发布:最全短期网络理财投资 编辑:程序博客网 时间:2024/05/22 16:11

几天没做LIS问题了,变得好生疏啊!

首先声明,此种思路是从别人那看到的,感觉很神奇,就按照他的方法试了试,AC了,不过我还不明白到底为什么这样做就是答案,此种方法大致是:把序列按照 l,w的顺序二级排序(升序)后,再求出w的最大下降子序列长度L,则L就是所要求的值。。。。我只是把这种思路实现了代码,就当是熟悉LIS问题吧,具体的原理和证明我还不会。。。。

这是我看到的

引用cc98 watashi 大牛的话: 

其实题目的意思就是把所有元素分为最少的堆数,每堆有l<=l' and w<=w' 按l排序后(l相等则按w),问题转化为把所有元素分为最少的堆数,每堆有w<=w'(l<=l' 显然成立) 即已知一个数列,要求最少用多少个不下降序列完全覆盖
可以证明不下降序列完全覆盖数就是最长下降子列的长度(记为L): 显然覆盖数不能比L小,否则由抽屉原理,必然有下降子列中两元素(a < b)在同一不下降须列中(a <= b),这是不可能的 由覆盖数可以取得L,而序列的每个元素在不同堆中,然后每次将元素“贪心”地分在堆中,这个过程和dp地求最长下降子列很像,可以构造解,也可以反证如果不能分号,与下降子列长度为L矛盾。
于是先将数列按照l,w的顺序进行快排,然后在求出w序列中的最长递减序列的长度就可以了.
深感数学知识欠缺啊!!!!!

我写的代码:

#include<stdio.h>#include<string.h>#include<stdlib.h>#define STOP system("pause")typedef struct{    int l;    int w;}NODE;NODE node[5005];int cmp(const void *a,const void *b){    if( ((NODE*)a)->l!=((NODE*)b)->l)      return ((NODE*)a)->l > ((NODE*)b)->l ? 1 : -1;      else       return    ((NODE*)a)->w>((NODE*)b)->w?1:-1;}int main(){    int t,n,i,j,max,d[5005];    scanf("%d",&t);    while(t--)    {          scanf("%d",&n);          for(i=0;i<n;i++)             scanf("%d%d",&node[i].l,&node[i].w);          qsort(node,n,sizeof(NODE),cmp);            d[0]=1;          for(i=1;i<n;i++)          {            d[i]=1;                for(j=0;j<i;j++)              if(node[j].w>node[i].w&&d[j]+1>d[i])                 d[i]=d[j]+1;         }         for(i=max=0;i<n;i++)           if(d[i]>max)             max=d[i];         printf("%d\n",max);    }    return 0;}    

原创粉丝点击