您的位置:首页 > 其它

uva 103 - Stacking Boxes

2011-04-04 23:17 369 查看
//可以使用佳哥介绍的DAG动规,不过麻烦些

//建议使用LIS ,那么排序函数Cmp()成了以问题关键, 可以把每个box的值从左到右作为比较的关键字, 这样人为的赋予一个优先级.

由于这些集合相互之间无序,我们需要先找到一种排序方法使得这些集合的顺序满足无后效性。这牵涉到如何判断两个集合的大小。





不难想到,如果集合A<集合B,当且仅当将集合A、B中的元素分别升序排列后,满足Ai<Bi。不难证明。
有了上面这条性质,我们可以按以下规则进行排序:先将所有集合中的元素分别排序,然后将第一个元素作为第一关键字,第二个元素作为第二关键字....依此类推,排序之。
容易知道这样整个序列就满足无后效性了,可以用最长不下降序列解决之。
//注意LIS和"无后效性"的关系
//无后效性:
//无后效性  
//无后效性是一个问题可以用动态规划求解的标志之一。   
//它是这样一种性质:某阶段的状态一旦确定,
//则此后过程的演变不再受此前各种状态及决策的影响,
//简单的说,就是“未来与过去无关”,
//当前的状态是此前历史的一个完整总结,
//此前的历史只能通过当前的状态去影响过程未来的演变。
//具体地说,如果一个问题被划分各个阶段之后,
//阶段I中的状态只能由阶段
//I-1中的状态通过状态转移方程得来,与其它状态没有关系,
//特别是与未发生的状态没有关系。
//从图论的角度去考虑,如果把这个问题中的状态定义成图中的顶点,
//两个状态之间的转移定义为边,
//转移过程中的权值增量定义为边的权值,
//则构成一个有向无环加权图,
//因此,这个图可以进行“拓扑排序”,
//至少可以按它们拓扑排序的顺序去划分阶段。


#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
struct Box{
    int len,a[12],num;
    bool operator < (const Box& b)const {
        //cout<<"UUU"<<endl;
        for(int i=0;i<b.len;i++)
            if(a[i]>=b.a[i]){
                //cout<<a[i]<<" "<<b.a[i]<<endl;
                //cout<<b.len<<endl;
                return 0;
            }
        return 1;
    }
};
int k,n,prior[35],sign[35],len,f[35],next[35],sss;
Box box[35],c[35];
int bsearch(Box& v){
    int l=1,r=len+1,m;
    while(l<r){
        //cout<<l<<" "<<r<<endl;
        m=l+(r-l)/2;
        //cout<<"m: "<<m<<endl;
        if(c[m]<v) l=m+1;
        else r=m;
    }
    return l;
}
void LIS(){
    int pos;
    len=1;
    c[len]=box[0];
    sign[1]=0;
    for(int i=1;i<k;i++){
        //cout<<"sda"<<endl;
        pos=bsearch(box[i]);
        c[pos]=box[i];
        sign[pos]=i;
        prior[pos]=sign[pos-1];
        if(pos>len)
            ++len;
    }
}
void find_res(int l,int i){
    if(l==len)
        return ;
    if(l==0){
        cout<<box[i].num;
        find_res(l+1,next[i]);
        return ;
    }
    cout<<" "<<box[i].num;
    find_res(l+1,next[i]);
    return ;
}
bool Cmp(Box i,Box j){
    for(int k=0;k<j.len;k++){
        if(i.a[k]!=j.a[k]){
            return i.a[k]<j.a[k];
        }
    }
    return 1;
}
int main()
{
    freopen("i.txt","r",stdin);
    while(cin>>k>>n){
        len=1;
        for(int i=0;i<k;i++){
            for(int j=0;j<n;j++){
                cin>>box[i].a[j];
            }
            box[i].len=n;
            box[i].num=i+1;
            sort(box[i].a,box[i].a+n);
        }
        sort(box,box+k,Cmp);
//        for(int i=0;i<k;i++){
//            for(int j=0;j<box[i].len;j++)
//                cout<<box[i].a[j]<<" ";
//            cout<<endl;
//        }
        f[k-1]=1;
        for(int i=k-2;i>=0;i--){
            f[i]=1;
            for(int j=i+1;j<k;j++)
                if(box[i]<box[j]&&f[i]<f[j]+1){
                    f[i]=f[j]+1;
                    next[i]=j;
                    if(f[i]>len){
                        len=f[i];
                        sss=i;
                    }
                }
        }
        cout<<len<<endl;
        find_res(0,sss);
        cout<<endl;
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: