poj 1065 Wooden Sticks

题目大意:给你n个木板,每个木板有两个属性L和W,按照某种顺序进行加工。规定对于相邻加工的两个木板1,2,如果满足L1≤L2且W1≤W2,则不需要耗费时间,否则就需要耗费1单元时间。现让你根据某种加工顺序,求出最短的用时。加工第1块木板用时1单元时间。

思路:求不下降子序列的组数的问题,根据Dilworth定理,链的最小组数等于反链的最大长度,于是该问题就转化为求最长下降子序列问题,DP解决。

(1)Dilworth定理的证明:

1.对于集合P,当P只有一个元素时,结论显然成立。

2.对于集合P,a为P的最大元素,令P‘ = P / {a}。假设P' 有k组链C1,C2, ......, Ck,和一个长度为k的反链A。显然有A∩Ci ≠∅,i=1,2,3,......,k。记Ci中的最大的元素为xi,令Ai为包含xi的长度为k的反链。对于任意的i与j,满足Ai ∩ Cj ≠ ∅。令y∈Ai ∩ Cj,则显然有y ≤ xj,所以xi !≥ xj,同理可得xj !≥ xi。根据i,j的任意性,所以A为长度为k的反链。

3.讨论a,当存在i∈{1,2,3,......,k},使得a≥xi,令K={a} ∪ Ci。则P / K能被分成k-1组链,最长反链为A / {xi},长度为k-1。因此加入K后满足要求;当不存在i,使a≥xi,P能被分成k+1组链,反链为A ∪ {a},长度为k+1,同样成立。

得证。

(2)最长下降子序列问题求解:设置dp[i]表示以第i个点结尾时的最长下降序列长度,则状态转移公式为:dp[i]=max(aj),j=1,2,3......n,aj=dp[j]+1当nj<ni ;否则aj=1。

 

#include <iostream>
#include <cstdio>
#include <algorithm>
 
using namespace std;
 
struct Stick
{
    int w,l;
    bool operator< (const Stick &a) const
    {
        if (w==a.w)
            return l<a.l;
        return w<a.w;
    }
}stick[5005];
 
int dp[5005];
 
int main(int argc, char** argv)
{
    int test_cases,n,i,j,ans;
    scanf("%d",&test_cases);
    while (test_cases--)
    {
        scanf("%d",&n);
        for (i=1;i<=n;i++)
            scanf("%d%d",&stick[i].l,&stick[i].w);
        sort(stick+1,stick+1+n);
        dp[1]=1;
        for (i=2;i<=n;i++)
            for (j=1,dp[i]=1;j<i;j++)
                if (stick[i].l<stick[j].l)
                    dp[i]=max(dp[i],dp[j]+1);
        ans=-1;
        for (i=1;i<=n;i++)
            if (dp[i]>ans)
                ans=dp[i];
        printf("%d\n",ans);
    }
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值