码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2015-07-25 00:08:20      阅读:138      评论:0      收藏:0      [点我收藏+]

标签:

此题倒是能用贪心骗点分...

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

(因为要尽量减少消耗, 可以考虑减小至和相邻的相同) 有了这个结论之后, 我们就考虑用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[n][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;
}

 

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

标签:

原文地址:http://www.cnblogs.com/yuchenlin/p/sjtu_oj_1282.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!