POJ 3670 && POJ 3671 (dp)

最长不下降子序列的应用嘛。两题都是一样的。

POJ 3670:求给定序列按递增或递减排列时,所需改变的最小的数字的数目。

POJ 3671:求给定序列按递增排列时,所需改变的最小的数字的数目。

思路就是求最长不下降子序列,然后剩下的就是需要改变的字母。

最长不下降子序列:(我之前有写过,不懂请戳)http://blog.csdn.net/darwin_/article/details/38360997

POJ 3670:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 30000+10
using namespace std;

int f[N],a[N];
int bin(int x,int r)   ////二分求比x大的第一个数字的位置
{
    int l=1,mid=(l+r)>>1,pos;
    while(l<=r)
    {
        mid=(l+r)>>1;
        if(a[mid]>x)
        {
            r=mid-1;
            pos=mid;
        }
        else
            l=mid+1;
    }
    return pos;
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%d",&f[i]);
    int ca=0,cb=0;
    memset(a,0,sizeof(a));
    for(int i=0;i<n;i++)
    {
        if(i==0) a[++ca]=f[i];
        else if(f[i]>=a[ca]) a[++ca]=f[i];
        else
        {
            int pos=bin(f[i],ca);
            a[pos]=f[i];
        }
    }
    int ans=n-ca;
    reverse(f,f+n);  //翻转一次,就是求原序列的最长不上升子序列
    memset(a,0,sizeof(a));
    for(int i=0;i<n;i++)
    {
        if(i==0) a[++cb]=f[i];
        else if(f[i]>=a[cb]) a[++cb]=f[i];
        else
        {
            int pos=bin(f[i],cb);
            a[pos]=f[i];
        }
    }
    ans=min(ans,n-cb);  //求两者的最小值,即是答案。
    printf("%d\n",ans);
    return 0;
}

POJ 3671:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 30000+10
using namespace std;

int f[N];
int bin(int x,int r)   //二分求比x大的第一个数字的位置
{
    int l=1,mid=(l+r)>>1,pos;
    while(l<=r)
    {
        mid=(l+r)>>1;
        if(f[mid]>x)
        {
            r=mid-1;
            pos=mid;
        }
        else
            l=mid+1;
    }
    return pos;
}
int main()
{
    int n;
    int cnt=0;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        int t;
        scanf("%d",&t);
        if(i==0) f[++cnt]=t;
        else if(t>=f[cnt]) f[++cnt]=t;
        else
        {
            int pos=bin(t,cnt);
            f[pos]=t;
        }
    }
    printf("%d\n",n-(cnt));
    return 0;
}

POJ 3670 && POJ 3671 (dp),布布扣,bubuko.com

时间: 2024-11-08 11:50:09

POJ 3670 && POJ 3671 (dp)的相关文章

POJ 3670 Eating Together (DP,LIS)

题意:给定 n 个数,让你修改最少的数,使得它变成一个不下降或者不上升序列. 析:这个就是一个LIS,但是当时并没有看出来...只要求出最长LIS的长度,用总数减去就是答案. 代码如下: #include <cstdio> #include <string> #include <cstdlib> #include <cmath> #include <iostream> #include <cstring> #include <s

POJ 3670 Eating Together 二分单调队列解法O(nlgn)和O(n)算法

本题就是一题LIS(最长递增子序列)的问题.本题要求求最长递增子序列和最长递减子序列. dp的解法是O(n*n),这个应该大家都知道,不过本题应该超时了. 因为有O(nlgn)的解法. 但是由于本题的数据特殊性,故此本题可以利用这个特殊性加速到O(n)的解法,其中的底层思想是counting sort分段的思想.就是如果你不会counting sort的话,就很难想出这种优化的算法了. O(nlgn)的单调队列解法,利用二分加速是有代表性的,无数据特殊的时候也可以使用,故此这里先给出这个算法代码

POJ 1384 Piggy-Bank 背包DP

所谓的完全背包,就是说物品没有限制数量的. 怎么起个这么intimidating(吓人)的名字? 其实和一般01背包没多少区别,不过数量可以无穷大,那么就可以利用一个物品累加到总容量结尾就可以了. 本题要求装满的,故此增加个限制就可以了. #include <stdio.h> #include <stdlib.h> #include <string.h> inline int min(int a, int b) { return a < b? a : b; } c

POJ 3280 Cheapest Palindrome DP题解

看到Palindrome的题目,首先想到的应该是中心问题,然后从中心出发,思考如何解决. DP问题一般是从更加小的问题转化到更加大的问题,然后是从地往上 bottom up地计算答案的. 能得出状态转移方程就好办了,本题的状态转移方程是: if (cowID[i] == cow{j]) tbl[id][i] = tbl[id][i+1];//相等的时候无需改动 else tbl[id][i] = min(tbl[!id][i+1] + cost[cowID[i]-'a'], tbl[!id][i

POJ 2342 (树形DP)

Anniversary party Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3863   Accepted: 2172 Description There is going to be a party to celebrate the 80-th Anniversary of the Ural State University. The University has a hierarchical structure

POJ 3034 Whac-a-Mole(DP)

题目链接 题意 : 在一个二维直角坐标系中,有n×n个洞,每个洞的坐标为(x,y), 0 ≤ x, y < n,给你一把锤子可以打到地鼠,最开始的时候,你可以把锤子放在任何地方,如果你上一秒在(x1,y1),那下一秒直线移动到的整数点(x2,y2)与这个点的距离小于等于d,并且当锤子移动(x2,y2)这个点时,所有在两点的直线上的整点数都可以打到.例如(0,0)移动到(0,3).如果(0,1),(0,2)有老鼠出现就会被打到.求能够打的最多老鼠. 思路 : Dp[i][j][k]代表点(i,j)

POJ 3616 Milking Time DP题解

典型的给出区间任务和效益值,然后求最大效益值的任务取法. 属于一维DP了. 一维table记录的数据含义:到当前任务的截止时间前的最大效益值是多少. 注意, 这表示当前任务一定要选择,但是最终结果是不一定选择最后一个任务,故此最后需要遍历找到table数组的最大值,当然计算过程中使用一个数记录最终最大值也是可以的. 状态转移方程就是: tbl[i] = MAX({from tbl[0]->tbl[i-1] }+ weight[i] ),即区间0到i-1加上i的当前效益值. #include <

poj 2948 Martian Mining (dp)

题目链接 完全自己想的,做了3个小时,刚开始一点思路没有,硬想了这么长时间,想了一个思路, 又修改了一下,提交本来没抱多大希望 居然1A了,感觉好激动..很高兴dp又有所长进. 题意: 一个row*col的矩阵,每个格子内有两种矿yeyenum和bloggium,并且知道它们在每个 格子内的数量是多少.最北边有bloggium的收集站,最西边有 yeyenum 的收集站. 现在要在这些格子上面安装向北或者向西的传送带(每个格子自能装一种).问最多能采到多少矿. 传送带只能直着走,不可弯曲,不能交

POJ 3017 单调队列dp

Cut the Sequence Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 8764   Accepted: 2576 Description Given an integer sequence { an } of length N, you are to cut the sequence into several parts every one of which is a consecutive subseque