zju 1108

大意是说给定n个数对(w1,s1),(w2,s2),(w3,s3)......(wn,sn)
现在要求一个序列(a1,a2,a3,...,am)使得有
Wa1<Wa2<Wa3<Wa4<。。。<Wam
Sa1>Sa2>Sa3>Sa4>。。。>Sam
现在要求出这个序列的最大长度,并且输出序列中的元素。
典型的DP,关键是这里是数对,将数对的第一个元素w从小到达的顺序来对数对排一次序,这样我们就可以不用考虑第一个数了,问题变成了典型的最长单调自序列问题。

my code:
#include  < iostream >
using   namespace  std;

#define  MAXN 1000
struct  mice {
    
int  w,s;
    
int  id;
};
bool   operator < const  mice &  m1, const  mice &  m2 ) {
    
if ( m1.w < m2.w )
    
return   true ;
    
if ( m1.w == m2.w )
    
return  m1.s > m2.s;
    
return   false ;
}

mice m[ MAXN
+ 1  ];    // 数对
int  p[ MAXN + 1  ];     // 记录结果

void  print(  int  id ) {
    
if ( id == 0  )  return ;
    print( p[ id ] );
    
if ( p[ id ] == 0  )
    cout
<< m[ id ].id << endl;
    
else   if ( m[ p[id] ].s > m[ id ].s && m[ p[ id ] ].w < m[ id ].w ) 
    cout
<< m[id].id << endl;
}
int  main(  ) {
    
int  w,s;
    
int  id = 0 ;
    
int  l[ MAXN + 1  ];        // DP用的数组
     while ( cin >> w >> s ) {
    id
++ ;
    m[ id ].w
= w;
    m[ id ].s
= s;
    m[ id ].id
= id;
    }
    sort( m
+ 1 ,m + id + 1  );
    l[ 
0  ] = 0 ;
    
for int  i = 1 ;i <= id;i ++  )
    l[ i ]
= 1 ;
    
// DP
     for int  i = 1 ;i <= id;i ++  )
    
for int  j = 1 ;j < i;j ++  ) {
        
if ( m[ j ].s > m[ i ].s && m[ j ].w < m[ i ].w && l[ j ] + 1 > l[ i ] ) {
        l[ i ]
= l[ j ] + 1 ;
        p[ i ]
= j;
            }
    }
    
int  maxid = 1 ;
    
for int  i = 2 ;i <= id;i ++  )
    
if ( l[ i ] > l[ maxid ] )
        maxid
= i;
    cout
<< l[ maxid ] << endl;
    print( maxid );
    
return   0 ;
}

你可能感兴趣的:(zju 1108)