最小调整代价-lintcode(c++)

lintcode91:最小调整代价
给一个整数数组,调整每个数的大小,使得相邻的两个数的差不大于一个给定的整数target,调整每个数的代价为调整前后的差的绝对值,求调整代价之和最小是多少。
例如:对于数组[1, 4, 2, 3]和target=1,最小的调整方案是调整为[2, 3, 2, 3],调整代价之和是2。返回2。
例如:对于数组[1, 5, 6]和target=1,最小的调整方案为[4,5,6],调整代价之和是3.返回3.

思路分析:
如何去构造最优子结构?如何存放数据?
对于这些问题,我想了一个小时,也没有想出个所以然。先说一下我自己的理解,开始的时候没有读清题意,认为修改一次的代价是1,1->2代价为1,2->5代价为1.印象中依稀记得动态规划算法实际上是对穷举法的变形。而具有n个数据的数组,最大的调整次数是n,最小的调整次数是0;如果采用穷举法,一共有2^n-1中可能。思路之后就断开了,如何存储数据,使用一维数组表示调整的次数,或者是使用二维数组,那么二维数组表示的是什么意思呢?带着这些疑问,我决定看一下别人的思路。
百度搜索到了解决问题的方法,涉及的陌生名词一共有3个。动态规划、滚动数组、记忆搜索。

如何存放数据?
建立一个二维数组M[A.size()][100],A.size()表示数组的大小,其中100表示0-99的100中可能。
M[i][j]表示的值的含义是第i个数据调整成j使用的最小调整次数,前面的i-1个数据已经最小的方式了。

如果构造最优子结构?
m[i][j] = min{ m[i-1][k]+abs(A[i]-j)/0 //其中k的取值是j-target到j+target };
一共需要三次循环,最外层循环A.size()次,中间循环100次,第三次循环2*target次

过程中的问题:知道思路之后写这个程序还是花了很长的时间,大约一个多小时。主要的原因是不明白m[i][j]是什么意思。此处说明一下,m[i][j]表示的含义是第i个数据,如果是j需要调整的最少次数。数据从i-1个到i个有意义的条件是A[i-1]和A[i]的绝对值之差小于target。(A表示数据)

代码如下
#include <vector>
#include <iostream>
#include <sstream>
#include <queue>
#include <cmath>
#include <climits>
using namespace std;
class Solution {
public:

int MinAdjustmentCost(vector<int> &A, int target) {

if(A.size() == 1 || A.size() == 0)
{
return 0;
}

//建立存放的容器
int ** m = new int* [A.size()];
for(int i = 0 ; i < A.size() ; i++)
{
m[i] = new int[100];
}

//初始化数据
for(int i = 0 ; i < 100 ;i ++)
{
m[0][i] = abs(i-A.at(0));
}

//循环获取数据
int min;
int min_j;
for(int i = 1 ; i < A.size() ;i++)
{
min_j = 100000;
for(int j = 0 ; j < 100 ; j++)
{
min = 100000;
//并不是全部位置可能只有一部分。
for(int z = -target ; z < target+1 ; z++)
{
//如果相差的数据,在target之内,不需要修改数据
if(z+j < 0 || z+j >= 100)
{
continue;
}
if(min > m[i-1][z+j] + abs(j-A.at(i)))
{
min = m[i-1][z+j] + abs(j-A.at(i));
}
}
m[i][j] = min;
if(m[i][j] < min_j)
{
min_j = m[i][j];
}
}

}
//最后的答案就是min;
return min_j;
}
};
int main()
{
vector<int> vec;
vec.push_back(1);
vec.push_back(100);
//vec.push_back(6);

Solution s;
cout << s.MinAdjustmentCost(vec,79);
return 0;
}

原文地址:https://www.cnblogs.com/qiny1012/p/9676816.html

时间: 2024-10-10 20:09:28

最小调整代价-lintcode(c++)的相关文章

LintCode-最小调整代价

给一个整数数组,调整每个数的大小,使得相邻的两个数的差小于一个给定的整数target,调整每个数的代价为调整前后的差的绝对值,求调整代价之和最小是多少. 样例 对于数组[1, 4, 2, 3]和target=1,最小的调整方案是调整为[2, 3, 2, 3],调整代价之和是2.返回2. 注意 你可以假设数组中每个整数都是正整数,且小于等于100. 分析:一般这种题,每个位置上都有很多种可能,基本上就是动态规划了,又因为每个位置最多100,于是可以枚举每个位置的数值,用dp[i][j]表示到第i个

[CTCI] 最小调整有序

最小调整有序 题目描述 有一个整数数组,请编写一个函数,找出索引m和n,只要将m和n之间的元素排好序,整个数组就是有序的.注意:n-m应该越小越好,也就是说,找出符合条件的最短序列. 给定一个int数组A和数组的大小n,请返回一个二元组,代表所求序列的起点和终点.(原序列位置从0开始标号,若原序列有序,返回[0,0]).保证A中元素均为正整数. 测试样例: [1,4,6,5,9,10],6 返回:[2,3] 先分别找到左边第一对逆序对与右边第一对逆序对,然后找出两个逆序对之间的最大值与最小值,然

【网络流24题】 No.12 软件补丁问题(最小转移代价 最短路)

[题意] T 公司发现其研制的一个软件中有 n 个错误, 随即为该软件发放了一批共 m 个补丁程序. 每一个补丁程序都有其特定的适用环境, 某个补丁只有在软件中包含某些错误而同时又不包含另一些错误时才可以使用.一个补丁在排除某些错误的同时, 往往会加入另一些错误.换句话说, 对于每一个补丁 i, 都有 2 个与之相应的错误集合 B1[i]和 B2[i],使得仅当软件包含 B1[i]中的所有错误, 而不包含 B2[i]中的任何错误时, 才可以使用补丁 i. 补丁 i 将修复软件中的某些错误 F1[

最小编辑代价

最小编辑代价问题: 对于两个字符串A和B,我们需要进行插入.删除和修改操作将A串变为B串,定义c0,c1,c2分别为三种操作的代价,请设计一个高效算法,求出将A串变为B串所需要的最少代价. 给定两个字符串A和B,及它们的长度和三种操作代价,请返回将A串变为B串所需要的最小代价.保证两串长度均小于等于300,且三种代价值均小于等于100. 测试样例: "abc",3,"adc",3,5,3,100 返回:8 问题分析:看到这道题,首先想到的是编辑距离问题,可以说是有异

hdu 3315 My Brute 费用流,费用最小且代价最小

很常见的想法了= = #include <stdio.h> #include <iostream> #include <string.h> using namespace std; const int N=400; const int MAXE=200000; const int inf=1<<30; int head[N],s,t,cnt,n,m,ans; int d[N],pre[N]; bool vis[N]; int q[MAXE]; int V[N

vijos - P1456最小总代价 (状态压缩DP + 记忆化搜索)

P1456最小总代价 Accepted 标签:[显示标签] 描述 n个人在做传递物品的游戏,编号为1-n. 游戏规则是这样的:开始时物品可以在任意一人手上,他可把物品传递给其他人中的任意一位:下一个人可以传递给未接过物品的任意一人. 即物品只能经过同一个人一次,而且每次传递过程都有一个代价:不同的人传给不同的人的代价值之间没有联系: 求当物品经过所有n个人后,整个过程的总代价是多少. 格式 输入格式 第一行为n,表示共有n个人(16>=n>=2): 以下为n*n的矩阵,第i+1行.第j列表示物

最小总代价 状压DP

描述 n个人在做传递物品的游戏,编号为1-n. 游戏规则是这样的:开始时物品可以在任意一人手上,他可把物品传递给其他人中的任意一位:下一个人可以传递给未接过物品的任意一人. 即物品只能经过同一个人一次,而且每次传递过程都有一个代价:不同的人传给不同的人的代价值之间没有联系:求当物品经过所有n个人后,整个过程的总代价是多少. 格式 输入格式 第一行为n,表示共有n个人(16>=n>=2):以下为n*n的矩阵,第i+1行.第j列表示物品从编号为i的人传递到编号为j的人所花费的代价,特别的有第i+1

vijos 1524 最小监视代价

背景 看到Vijos上此类型的题目较少,特地放一道上来给大家练练. 描述 由于yxy小朋友做了一些不该做的事,他被jzp关进了一个迷宫里.由于jzp最近比较忙,疏忽大意了一些,yxy可以在迷宫中任意走动.整个迷宫可以被看作是一个无向图.迷宫中有一些结点有传送点,可以让他逃离这个迷宫.jzp发明了一种机器人,可以监视迷宫中的道路,被监视的道路yxy不能通过,我们简单的认为监视一条道路的代价即为这条道路的长度.现在jzp正在忙,请你编一个程序算出使yxy无法逃离迷宫的最小监控总代价.(yxy一开始在

[Vijos P1524]最小监视代价

题目大意:有一些点和一些边,每条边有一个监视代价.一个人从1号点出发,到达某些“传送点”可以逃生.但被监视的边就不能走了.要你用最小的监视代价使得那个人无法传送. 解题思路:求最小割.先建一个超级汇点$n+1$,把所有传送点连上这个超级汇点,然后根据“最小割=最大流”的定理,跑最大流即可.注意无向图. 以下为Dinic算法代码. C++ Code: #include<cstdio> #include<vector> #include<cstring> #include&