题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1160
题目大意:给出多个数据组(最多1000个),terminated by end of file,对于第 i 个数据组有两个数据:W[i] 和 S[i],要求找出一串数据组,在这串数据组中,W[i] 递增,对应的 S[I] 递减,要求数据串尽可能长。
解题思路:
DP。用数组dp[i] 表示以第 i 组数据为结尾的最长长度。
由于有每组有两个数据,我们可以一上来先对其中一种数据进行排序。我选择先把 W[i] 按从小到大排序,对于W[i] 相同的数据组,我们从大到小排序。这样一来,我们便可以少考虑一种数据,W[i] 已经能够保证合法,只要不是相等的情况。在外层循环中从头枚举各个数据组 i,计算dp[i] ,在内层循环中枚举第1至 i-1 组数据组 j,dp[i] = max( dp[j] + 1),当然,第 i 个数据组要满足W[i] < W[j] && S[i] > S[j]。
用 pre[] 数组记录路径。
AC代码:
1 #include <vector> 2 #include <cstdio> 3 #include <algorithm> 4 using namespace std; 5 const int maxn=1000+10,inf=0x7ffffff; 6 struct node{ 7 int W,S,ind; 8 }n[maxn]; 9 int W[maxn],S[maxn],dp[maxn],pre[maxn],path[maxn]; 10 bool cmp(const node &a,const node &b){ 11 if(a.W<b.W) return 1; 12 else if(a.W==b.W&&a.S>b.S) return 1; 13 return 0; 14 } 15 int main() 16 { 17 int num=1; 18 while(scanf("%d%d",&n[num].W,&n[num].S)==2){ 19 pre[num]=0; 20 n[num].ind=num; 21 dp[num]=1; 22 num++; 23 } 24 sort(n+1,n+num,cmp); 25 int ans=0,aj; 26 for(int i=1;i<num;i++){ 27 for(int j=1;j<i;j++){ //因为有了前面的排序,j必须小于i,不然之后的j不合法 28 if(n[j].W<n[i].W&&n[j].S>n[i].S&&dp[i]<dp[j]+1){ 29 dp[i]=dp[j]+1; 30 pre[i]=j; 31 if(dp[i]>ans){ 32 aj=i; 33 ans=dp[i]; 34 } 35 } 36 } 37 } 38 39 int t=0,ti=aj; 40 while(ti!=0){ 41 path[t++]=ti; 42 ti=pre[ti]; 43 } 44 printf("%d ",ans); 45 while(t>0){ 46 t--; 47 printf("%d ",n[path[t]].ind); 48 } 49 return 0; 50 }