LIS application

http://codeforces.com/contest/4/problem/D

这道题目是一道LIS,后来也想到了,但是想dp[i]是以为尾元素为序列的最大值,从输入数据开始dp即使找到了最大值他的起点也未必是>w >h的,
然后觉得有点麻烦了,后来发现可以先把<=的都删掉,过滤一遍,这样剩下的任意一个值都是符合头的性质的,也就是严格的从头开始的递增序列。

但是WA了一次,发现dp之后构造解,忘记加递增的条件了(!j || (data[j-1].w<data[i-1].w && data[j-1].h<data[i-1].h)), 还漏了一次!j的判断,
这里其实因为只要返回任意解,直接for就可以解决了,如果是返回所有解,由于有多个分支,因此需要dfs每个分支了。

struct Node
{
    int w, h;
    int in;
    bool operator<(Node n) const
    {
        if(w!=n.w) return w<n.w;
        else return h<n.h;
    }
};
int main()
{
/*
#ifndef ONLINE_JUDGE
    freopen ("in.txt" , "r" , stdin);
    freopen ("out.txt" , "w" , stdout);
#endif
*/
    int n, w, h, w1, h1;
    cin>>n>>w>>h;
    int dp[n+1];
    vector<Node> data;
    for(int i=0;i<n;i++)
    {
        cin>>w1>>h1;
        if(w1>w && h1>h)
            data.push_back({w1,h1,i+1});
    }
    sort(data.begin(), data.end());
    n=data.size();
    dp[0]=0;
    int maxi=0, maxdp=dp[0];
    for(int i=1;i<=n;i++)
    {
        dp[i]=0;
        for(int j=0;j<i;j++)
        {
            if(!j || (data[j-1].w<data[i-1].w && data[j-1].h<data[i-1].h))
                dp[i]=max(dp[i], dp[j]+1);
        }
        if(dp[i]>maxdp) maxdp=dp[i], maxi=i;
    }
    vector<int> ans;
    for(int i=maxi;i>0;)
    {
        ans.push_back(data[i-1].in);
        int j;
        for(j=0;j<i;j++)
        {
            if(dp[i]==dp[j]+1 && (!j || (data[j-1].w<data[i-1].w && data[j-1].h<data[i-1].h)))
                break;
        }
        i=j;
    }
    reverse(ans.begin(), ans.end());
    cout<<ans.size()<<endl;
    for(auto e: ans) cout<<e<<" ";
    cout<<endl;
    return 0;
}

Posted by richard爱闹 - 3月 5 2015
如需转载,请注明: 本文来自 Richard