您的位置:首页 > 其它

【算法学习笔记】83.排序辅助 动态规划 SJTU OJ 1282 修路

2015-07-24 23:35 489 查看
此题倒是能用贪心骗点分...

其实对于每一个位置 , 我们知道最后的改善结果一定是原数列中的数 .

(因为要尽量减少消耗, 可以考虑减小至和相邻的相同) 有了这个结论之后, 我们就考虑用dp来做这件事情

首先 存下所有数据于 data[]

排序data 得到 data_sort[]

然后用dp[i][j]来表示 前i个元素 以data_sort[j]为结尾 转换成 递增序列的耗费.

那么我们可以知道

dp[i][j] = min({dp[i-1][k]}) + | data[i]- data_sort[j] |

所以直译为:

for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
for (int k = 1; k <= j ; ++k)
tmp = min(tmp,dp[i-1][k]);
dp[i][j] = tmp + abs(arr[j]-data[i]);


但是可以有大大的优化, 因为第三重循环式为了计算从dp[i][1]到dp[i][j]的最小值, 我们可以利用一个数组来dp计算这个最小值.

所以用ass[i][j]来表示从dp[i][1]到dp[i][j]的最小值,

那么对于ass[i][j] 的更新 可有

ass[i][j] = min(dp[i][j],(j==1 ? INF : (ass[i][j-1])));

当j=1时,ass[i][1] = dp[i][1]

当j>=2时,ass[i][j] = min(dp[i][j],ass[i][j-1]);

所以要先更新dp[i][j]再更新ass[i][j]

因为j的顺序是从1到n, data_sort[j]是从小到大的,所以就维护了整体的单调性 从而得到了答案.

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
typedef unsigned long long ull;
const int MaxN = 2000+10;
const int INF = 2147483600;
int n;

int data[MaxN];
int data_sort[MaxN];
int data_sort_d[MaxN];
int dp[MaxN][MaxN]; //dp[i][j] 表示前i个数 修补为以data_sort[j]为结尾的序列时的消耗最小体力值
int ass[MaxN][MaxN];//用来辅助求最小值的dp过程

bool cmp_int_d(const int& a, const int& b){
return a>b;
}

void init(){
cin>>n;
for (int i = 1; i <= n; ++i)
{
cin>>data[i];
data_sort[i] = data[i];
}
sort(data_sort+1,data_sort+n+1);
for (int i = 1; i <= n; ++i)
{
data_sort_d[i] = data_sort[n+1-i];
}
memset(dp,0,sizeof(dp));
memset(ass,0,sizeof(ass));
}

int build(int* arr){

//cout<<"-----\n";
for (int i = 1; i <= n; ++i){
for (int j = 1; j <= n; ++j){
// for (int k = 1; k <= j ; ++k)
//     tmp = min(tmp,dp[i-1][k]);
dp[i][j] = ass[i-1][j] + abs(arr[j]-data[i]);
//cout<<dp[i][j]<<" ";
ass[i][j] = min(dp[i][j],(j==1 ? INF : (ass[i][j-1])));
//cout<<"("<<ass[i][j]<<") ";
}
//cout<<endl;
}
int ans = INF;
for (int i = 1; i <= n; ++i)
ans = min(ans,dp
[i]);
return ans;
}

int main(int argc, char const *argv[])
{
init();
int a = build(data_sort);
int d = build(data_sort_d);
//cout<<a<<" "<<d<<endl;
cout<<min(a,d)<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: