• Codeforces713C Sonya and Problem Wihtout a Legend(DP)


    题目

    Source

    http://codeforces.com/problemset/problem/713/C

    Description

    Sonya was unable to think of a story for this problem, so here comes the formal description.

    You are given the array containing n positive integers. At one turn you can pick any element and increase or decrease it by 1. The goal is the make the array strictly increasing by making the minimum possible number of operations. You are allowed to change elements in any way, they can become negative or equal to 0.

    Input

    The first line of the input contains a single integer n (1 ≤ n ≤ 3000) — the length of the array.

    Next line contains n integer ai (1 ≤ ai ≤ 109).

    Output

    Print the minimum number of operation required to make the array strictly increasing.

    Sample Input

    7
    2 1 5 11 5 9 11
    5
    5 4 3 2 1

    Sample Output

    9
    12

    分析

    题目打给说给一个序列,可以进行若干次操作,每次操作选择一个数让它+1或-1,问最少要几次操作使得序列变为严格单调递增序列。

    首先考虑不是严格递减的情况,这其实是个经典问题的样子,太弱都没做过。。

    • 不严格递减最后修改完成后的各个数一定是原序列中的某一个数

    这个大概可以这么理解:原序列,从左到右扫过去,如果左边的大于右边的,要嘛左边的减掉使其等于右边的,要嘛右边的加上使其等于左边的。


    于是就可以考虑用dp来做了:

    • dp[i][j]表示序列前i个数都单调递增且第i个数更改为不大于原序列中第j个数的最少代价
    • 转移就是dp[i][j]=min(dp[i][j-1],dp[i-1][j]+abs(a[i],b[j])),a是原序列,b是原序列排序去重的序列

    回到原问题,原问题是求严格单调递增,这个可以转化成不严格单调递增:

    • 让原序列每个数a[i]减去i

    这样转化可行是因为:

    这个转化感觉挺神奇的。。

    代码

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    long long d[3333][3333],a[3333],b[3333];
    int main(){
    	int n;
    	scanf("%d",&n);
    	for(int i=1; i<=n; ++i){
    		scanf("%d",a+i);
    		a[i]-=i;
    		b[i]=a[i];
    	}
    	sort(b+1,b+1+n);
    	int bn=unique(b+1,b+1+n)-b-1;
    	memset(d,127,sizeof(d));
    	for(int i=1; i<=bn; ++i){
    		d[1][i]=min(d[1][i-1],abs(a[1]-b[i]));
    	}
    	for(int i=2; i<=n; ++i){
    		for(int j=1; j<=bn; ++j){
    			d[i][j]=min(d[i][j-1],d[i-1][j]+abs(a[i]-b[j]));
    		}
    	}
    	printf("%lld",d[n][bn]);
    	return 0;
    }
    
  • 相关阅读:
    vue_组件化开发
    C++ / C# 访问网络共享文件夹
    PetaLinux 设置操作系统内存
    linux 不用./ 直接执行程序
    Visual Studio Code 开发环境搭建 —— C# 扩展插件
    Visual Studio Code 调试项目时传参
    PetaLinux 安装
    Ubuntu 报 "xxx is not in the sudoers file.This incident will be reported" 错误解决方法
    常用 Linux 命令
    搭建 Git 服务器(Ubuntu 系统)
  • 原文地址:https://www.cnblogs.com/WABoss/p/5876968.html
Copyright © 2020-2023  润新知