简单dp,是最长上升子序列问题的变种。要注意样例,对于其输出结果,得到得先将输入的序列进行排序,然后再动规。由于要输出对应的序列号,所以这里我们就直接采用O(n^2)算法。由于输出的序列是按照给定的要求的,所以这里我们可以从数组尾进行动规计算,然后不断的记录一个节点的下一个节点。这点与前一个动规的输出相似。代码如下:
/*
ID: csuchenan
PROG: 10131 - Is Bigger Smarter?
LANG: C++
*/
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
using namespace std ;
struct Node
{
int w ;
int s ;
int index ;
}node[1005] ;
int dp[1005] ;//用于存储结果
int pr[1005] ;//用于对应的前驱点
int n ;
int cmp(const void * a , const void * b)
{
Node * c = (Node *)a ;
Node * d = (Node *)b ;
if(c->w!= d->w)
return c->w - d->w ;
return c->s - d->s ;
}
int main()
{
// freopen("10131.in" , "r" , stdin) ;
// freopen("10131.out" , "w" , stdout) ;
int i ;
i = 0 ;
n = 0 ;
while(cin>>node[i].w>>node[i].s)
{
node[i].index = i + 1 ;
i++ ;
}
n = i ;
//先进行排序
qsort(node , n ,sizeof(node[0]) , cmp) ;
int j ;
int temp ;
int index ;
memset(dp , 0 , sizeof(dp)) ;
memset(pr , 0 , sizeof(pr)) ;
dp[n - 1] = 1 ;
pr[n - 1] = -1 ;
for(i = n - 2 ; i >= 0 ; i --)
{
temp = 0 ;
index = -1 ;
for(j = n - 1 ; j > i ; j --)
{
if(temp < dp[j] && node[i].w < node[j].w && node[i].s > node[j].s)
{
temp = dp[j] ;
index = j ;
}
}
dp[i] = temp + 1 ;
pr[i] = index ;
}
j = 0 ;
for(i = 1 ; i < n ; i ++)
{
if(dp[i] > dp[j])
j = i ;
}
cout<<dp[j]<<endl ;
while(j!=-1)
{
cout<<node[j].index<<endl ;
j = pr[j] ;
}
return 0 ;
}