2

dilworth定理+属性排序(木棍加工)

 P1233 木棍加工

题目描述

一堆木头棍子共有n根,每根棍子的长度和宽度都是已知的。棍子可以被一台机器一个接一个地加工。机器处理一根棍子之前需要准备时间。准备时间是这样定义的:

第一根棍子的准备时间为1分钟;

如果刚处理完长度为L,宽度为W的棍子,那么如果下一个棍子长度为Li,宽度为Wi,并且满足L>=Li,W>=Wi,这个棍子就不需要准备时间,否则需要1分钟的准备时间;

计算处理完n根棍子所需要的最短准备时间。比如,你有5根棍子,长度和宽度分别为(4, 9),(5, 2),(2, 1),(3, 5),(1, 4),最短准备时间为2(按(4, 9)、(3, 5)、(1, 4)、(5, 2)、(2, 1)的次序进行加工)。

输入输出格式

输入格式:

 

第一行是一个整数n(n<=5000),第2行是2n个整数,分别是L1,W1,L2,w2,…,Ln,Wn。L和W的值均不超过10000,相邻两数之间用空格分开。

 

输出格式:

 

仅一行,一个整数,所需要的最短准备时间。

 

输入输出样例

输入样例#1: 
5
4 9 5 2 2 1 3 5 1 4
输出样例#1: 
2

拿到这道题,第一思路:暴力,用骚操作优化一下,说不定会快的飞起呢!!!
但实际上,只要稍微一思考,就会发现这就是一道赤裸裸的dp啊。
我们进一步分析,会发现,要同时满足l0>l1,w0>w1,就说明它有两种属性,傻子都看的出这题的贪心就是使序列满足两种属性的同时,尽可能多的
找出最长上升子序列,对不对?
同时又由于dilworth定理我们知道,同一个序列里,最长上升子序列的个数就等于最长不上升子序列的长度,所以我们又把问题装换成了求最长不上升子序列
我相信大家一定都会O(nlogn)算法来求,对不对?
所以我在此不再赘述。
但是还有一个问题,如何处理双重属性的问题,我们有一个通用的方法,就是将其中的一重属性排序,来求另一重的目标序列,这个东西啊,我讲也讲不清楚
自己多体会体会,再用一些骚操作,我相信你会明白的,对不对?
诺,下面是代码(我用STL写的)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 5000+5

using namespace std;

int n,f[maxn];
struct stack{
    int l,w;
}s[maxn];

bool cmp(const stack &a,const stack &b)
{
    return a.l>b.l;
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
          scanf("%d%d",&s[i].l,&s[i].w);
          
    sort(s+1,s+1+n,cmp);//给属性降维
    /*求最长不上升子序列*/
    int len=0;
    for(int i=1;i<=n;i++)
    {
        if(s[i].w>f[len])
        {
            f[++len]=s[i].w;
        }
        else{
            int k=lower_bound(f+1,f+1+len,s[i].w)-f;
            f[k]=s[i].w;
        }
    }
printf(
"%d",len);
//长度即使答案。

return 0; }
我还是很蒟蒻的,所以如果有任何漏洞的话,还请读者大老爷们指出QAQ
谢谢大家!……!
posted @ 2018-03-23 21:58  DDYYZZ  阅读(452)  评论(0编辑  收藏