2015 百度之星 1005 序列变换 动态规划

序列变换

Time Limit: 20 Sec  Memory Limit: 256 MB

题目连接

http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=601&pid=1003

Description

我们有一个数列A1,A2...An,你现在要求修改数量最少的元素,使得这个数列严格递增。其中无论是修改前还是修改后,每个元素都必须是整数。 请输出最少需要修改多少个元素。

Input

第一行输入一个T(1≤T≤10),表示有多少组数据

每一组数据:

第一行输入一个N(1≤N≤105),表示数列的长度

第二行输入N个数A1,A2,...,An。

每一个数列中的元素都是正整数而且不超过106。

 

Output

对于每组数据,先输出一行

Case #i:

然后输出最少需要修改多少个元素。

 

Sample Input

2
2
1 10
3
2 5 4

 

Sample Output

Case #1:
0
Case #2:
1

 

HINT

题意

 

题解:

先减去下标,然后求最长上升子序列,这是道原题,见到很多次了= =

答案就是n-最长上升子序列长度

代码:

 

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;

const int MAXN=100010;
int a[MAXN],b[MAXN];

//用二分查找的方法找到一个位置,使得num>b[i-1] 并且num<b[i],并用num代替b[i]
int Search(int num,int low,int high)
{
    int mid;
    while(low<=high)
    {
        mid=(low+high)/2;
        if(num>=b[mid])  low=mid+1;
        else   high=mid-1;
    }
    return low;
}
int DP(int n)
{
    int i,len,pos;
    b[1]=a[1];
    len=1;
    for(i=2;i<=n;i++)
    {
        if(a[i]>=b[len])//如果a[i]比b[]数组中最大还大直接插入到后面即可
        {
            len=len+1;
            b[len]=a[i];
        }
        else//用二分的方法在b[]数组中找出第一个比a[i]大的位置并且让a[i]替代这个位置
        {
            pos=Search(a[i],1,len);
            b[pos]=a[i];
        }
    }
    return len;
}


int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int T    ;
    int iCase = 0;
    scanf("%d",&T);
    while(T--){
        iCase++;
        int n;
        scanf("%d",&n);
        for(int i = 1;i <= n;i++){
            scanf("%d",&a[i]);
            a[i] -= i;
        }
        printf("Case #%d:\n",iCase);
        printf("%d\n",n - DP(n));
    }
    return 0;
}

 

你可能感兴趣的:(动态规划)