题目:免费午餐

题目描述

为了增加顾客,Sally的店铺决定提供免费午餐,顿时门庭若市,但是不久Sally的原材料不足了….因此Sally决定公布一项决定:凡是来本店吃免费午餐的,一天吃能吃一次,吃的数量必须比上一次吃的少, 点的必须在上一次后面,且免费午餐将只有N个种类任君选择,为了能吃到最多的免费午餐,你将如何安排每日吃的数量呢?

输入格式

第一行一个数N,表示免费午餐的种类(0<=N<=100000)
第二行N个数,表示每个免费午餐的数量(0<=数量<=100000)

输出格式

一个数,表示最多能吃多少天.

 

 

分析:

典型的DP,但朴素的DP已不能满足该题的数据,因此就用到了刚才写的求最大不降序列算法了,只需小小的改动即可。

该题数据十分阴险,竟有数据等于0的情况,需注意。

 

代码实现:—————————————————————————————————————————————————

#include<iostream>
using namespace std;

int a[100001],c[100001];

int find(int len,int n){
    int left=1,right=len,mid;
    while(left<=right)
    {
     mid=(left+right)/2;
     if(c[mid]==n) return mid;
     else if(c[mid]>n) left=mid+1;
     else if(c[mid]<n) right=mid-1;
                      }
     return left;
    }

int main()
{
    int n,i,j,k,len;bool p=1;
    cin>>n;   if(n==0) {cout<<0;return 0;}
    for(i=1;i<=n;i++)
    {cin>>a[i];if(a[i]!=0) p=0;}
   
    if(p==1) {cout<<0;return 0;}
   
    c[1]=a[1];
    len=1;
   
    for(i=1;i<=n;i++)
    {
     if(a[i]==0) continue;
     j=find(len,a[i]);
     c[j]=a[i];
     if(j>len)
     len=j;          
                     }
   
    cout<<len;
    system("pause");
    return 0;
    }

 

转载于:https://www.cnblogs.com/noip/archive/2011/12/17/2291261.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值