【Coder Force】#360B - Levko and Array(DP 二分枚举)

题目大题:CF上的题目还是比较容易读懂的。这道题的意思嘛,他是说,有一个不超过2000个数的数组,每一个数与后面的数的绝对值称为value,那么所有当中最大的value就是整个数组的value,现在你有k次变换,每一次可以将其中的一个数变为任何一个使得数组价值最小的数。

假如题目的价值是所有的之和,也可以用这道题的方法。

思路:

dp[i]表示的是到i这个位置,使得数组符合条件的最少变换次数。

这个符合条件就奇妙了,这个符合条件是由你定的,最终的符合条件就是答案。

简单来说:你举例一个答案,放进去,看看能不能使得整个数组的变换次数小于等于给定的K次,假如可以的话,那么这个数存起来。

接下来我们尝试更大一点可以不可以呢?可以的话重复以上操作,不可以的话就是之前的数拉。

我们枚举的范围是0-2e9,这么大的范围,傻眼了,不急,二分搜索是一个不错的方法。

好了,方法说完了。接下来是考验你DP功底的时候了,可惜这边我差劲的很,没办法给大家切入点和突破性的建议和见解了。

只能给大家讲一下这个模型,放心,等我学成之后我定给大家剖析每一道我A的题。

dp[i]=min(dp[i],dp[j]+i-j-1)(1

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int dp[2010];
int a[2010];
const int inf = 2e9;
int n, m;

bool  bs(long long mid)
{
    for (int i = 1; i <= n; i++)
    {
        dp[i] = i - 1;
        for (int j = 1; j < i; j++)
        if (abs(a[i] - a[j]) <= (i - j)*mid)
            dp[i] = min(dp[i], dp[j] + (i - j - 1));
        if (dp[i] + n - i <= m)return true;
    }
    return false;
}
int main()
{
    while (cin >> n >> m)
    {
        for (int i = 1; i <= n; i++)
            scanf("%d", &a[i]);
        long long l = 0, r = inf;
        int ans = 0;
        while (l <=r)
        {
            long long mid = (l + r) >> 1;//int+int会超过int的范围,导致爆掉了。= =
            if (bs(mid))
            {
                ans = mid; r = mid - 1;
            }
            else l = mid + 1;
        }
        cout << ans << endl;
    }
}
时间: 2024-10-12 12:54:53

【Coder Force】#360B - Levko and Array(DP 二分枚举)的相关文章

POJ-2533最长上升子序列(DP+二分)(优化版)

Longest Ordered Subsequence Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 41944   Accepted: 18453 Description A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence of the given numeric sequence (a1, a2, ...

hdu3586 树形dp+二分求解

http://acm.hdu.edu.cn/showproblem.php?pid=3586 Problem Description In the battlefield , an effective way to defeat enemies is to break their communication system. The information department told you that there are n enemy soldiers and their network w

HDU 3433 (DP + 二分) A Task Process

题意: 有n个员工,每个员工完成一件A任务和一件B任务的时间给出,问要完成x件A任务y件B任务所需的最短时间是多少 思路: DP + 二分我也是第一次见到,这个我只能说太难想了,根本想不到. dp[i][j]表示在t时间内前i个人完成j件A任务后所能完成B任务的最大数量. 代码中还有一些注释. 1 //#define LOCAL 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 using

[数位dp+二分] fzu 1074 Nancy&#39;s Birthday

题意:给m,n,问含有m个0的第k个数,是几位数,并且最高位是多少. 思路:和普通数位dp一样,加上个二分. 然后就是注意一下,极限值测试下能否算出来,这题极限值很大! 代码: #include"cstdlib" #include"cstdio" #include"cstring" #include"cmath" #include"queue" #include"algorithm" #

Codeforces 360C Levko and Strings dp

题目链接:点击打开链接 题意: 给定长度为n的字符串s,常数k 显然s的子串一共有 n(n-1)/2 个 要求找到一个长度为n的字符串t,使得t对应位置的k个子串字典序>s #include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> #include<vector> #include<set> using namespace std; #

poj3208 Apocalypse Someday 数位dp+二分 求第K(K &lt;= 5*107)个有连续3个6的数。

/** 题目:poj3208 Apocalypse Someday 链接:http://poj.org/problem?id=3208 题意:求第K(K <= 5*107)个有连续3个6的数. 思路:数位dp+二分. dp[i][j]表示长度为i,前缀状态为j时含有的个数. j=0表示含有前导0: j=1表示前缀连续1个6 j=2表示前缀连续2个6 j=3表示前缀连续3个6 j=4表示前缀不是6: */ //#include<bits/stdc++.h> #include<cstr

hdu 1025 Constructing Roads In JGShining’s Kingdom 【dp+二分】

题目链接:http://acm.acmcoder.com/showproblem.php?pid=1025 题意:本求最长公共子序列,但数据太多.转化为求最长不下降子序列.太NB了.复杂度n*log(n). 解法:dp+二分 代码: #include <stdio.h> #include <string.h> #include <vector> #include <string> #include <algorithm> #include <

Codeforces 57C Array dp暴力找规律

题目链接:点击打开链接 先是计算非递增的方案, 若非递增的方案数为x, 则非递减的方案数也是x 答案就是 2*x - n 只需求得x即可. 可以先写个n3的dp,然后发现规律是 C(n-1, 2*n-1) 然后套个逆元即可. #include<iostream> #include<cstdio> #include<vector> #include<string.h> using namespace std; #define ll long long #def

hdu2993之斜率dp+二分查找

MAX Average Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5825    Accepted Submission(s): 1446 Problem Description Consider a simple sequence which only contains positive integers as