杭电1160-FatMouse’s Speed 动态规划 --最大递增子串

题目连接

题目卡了好久,题目大概意思是给你未知数量的老鼠的体重和速度,让我们找出最长的序列,序列满足老鼠体重增加,速度减小,其实就是先对体重排序 ,然就问题就成了最大递增子串  

对于输入有一个小技巧, 也不能说是技巧, 就是告诉你未知数量的数据 用Ctrl➕z结束输入   以前是知道的,好就没敲就忘记了,

 

可以把这题的DP时候的代码看做是最大递增子串的模版了

平常的最大递增子串是只要能够输出一个最大或者最小的值就行了,但是这道题还要输出满足符合条件的按顺序的老鼠,这边我自己是用了一个front数组 存这只老鼠的上一只老鼠是哪一只。然后递归找到最上面的老鼠,回溯打印。

 

最大递增自串的意思就是,给你一个序列,这个序列是乱序的例如{1,7,4,5,7,9,2,3} 要你从中找出如增的子序列,

{1,7(第一个)}就是一个递增子序列,{1,4,5}(中间可以略过数字,这个序列略过了7) 也是一个子序列,

这个序列最大的子序列是{1,4,5,9}共4个数字。

解这种题的思路是用一个dp数组, dp[i]表示第i个元素的最长子序列,然后第i+1个元素就是要去判断是否大于第i个元素,是的话就可以让dp[i+1]==dp[i]+1,但是不一定只要dp第i+1个元素大于第i个就一定是在第i个元素时的最大子序列,可以是0~i中的任意一个,取最大值,用两层循环来实现,具体可以看下面代码

#include <set> 
#include <queue> 
#include<algorithm>
#include <iostream>
#include<string.h>
#include<map>
#include<stack>
#include<string> 
#include <stdio.h>
#include<math.h>
#include <cstring> 
using namespace std;
struct node {
    int weight;
    int speed;
    int num;
}; 
int front[10010];
node s[10010];
bool cmp(node a,node b){
    return a.weight<b.weight;
}
void print(int n){
    if(front[n]!=-1)
        print(front[n]);
    cout<<s[n].num+1<<endl;
}
int main()
{   int k=0;
    memset(front,-1,sizeof(front));
    while(scanf("%d%d",&s[k].weight,&s[k].speed)!=EOF)
    {
        s[k].num=k;
        k+=1;
    }
    sort(s,s+k,cmp);
  /*  for(int i=0;i<k;i++){
        cout<<s[i].weight<<"  "<<s[i].speed<<"  "<<s[i].num+1<<endl;
    }*/
    int max=1;
    int max_num=0;
    int dp[10010]={0}; 
    for(int i=0;i<k;i++){
        dp[i]=1;//每只老鼠开始都要先包括自己在内。 
        for(int j=0;j<i;j++){
            if(s[i].weight>s[j].weight&&s[i].speed<s[j].speed){
                if(dp[i]<dp[j]+1){
                    dp[i]=dp[j]+1;
                    front[i]=j;//记录一下这只老鼠的上一只是谁。 
                    if(max<dp[i]){
                        max=dp[i];
                        max_num=i;
                    }
                }
            }
        }
    }
   /* for(int i=0;i<k;i++){
        cout<<s[i].weight<<"  "<<s[i].speed<<"  "<<s[i].num+1<<"  ";
        cout<<dp[i]<<"  "<< s[front[i]].num+1<<"  ";
        cout<<front[i]<<endl;
    }
  */
    cout<<max<<endl;
    //cout<<max_num<<endl;
    print(max_num);
    return 0;
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值