当前位置: 首页 > news >正文

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

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

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

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

 

转载于:https://www.cnblogs.com/yuchenlin/p/sjtu_oj_1282.html

相关文章:

  • 基于Qt5.5.0的sql,C++备忘录软件的编写
  • IDFactory int类型ID生成器
  • SharePoint 2013 内容部署报错
  • 如何在CentOS6.5中进行PPPOE拨号上网
  • Ubuntu下安装Atom及使用
  • PHP读取超大文件的实例代码
  • YxdIOCP (DIOCP修改版)
  • ocp-051-3
  • java实现多线程的三种方式
  • ava垃圾加收机制和ios的arc有什么区别
  • Linux iostat命令详解
  • 建立完整的单向动态链表(包括初始化、创建、插入、删除、查找、销毁、输出)...
  • 【Go】Linux下使用Sublime Text搭建开发环境
  • 双nginx(主备、主主)反向代理tomcat实现web端负载均衡
  • c# 笔试题及参考答案大全
  • 分享的文章《人生如棋》
  • 【笔记】你不知道的JS读书笔记——Promise
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • CoolViewPager:即刻刷新,自定义边缘效果颜色,双向自动循环,内置垂直切换效果,想要的都在这里...
  • ECMAScript入门(七)--Module语法
  • Eureka 2.0 开源流产,真的对你影响很大吗?
  • java第三方包学习之lombok
  • JS变量作用域
  • Mocha测试初探
  • Solarized Scheme
  • webpack+react项目初体验——记录我的webpack环境配置
  • Xmanager 远程桌面 CentOS 7
  • 多线程事务回滚
  • 浮动相关
  • 极限编程 (Extreme Programming) - 发布计划 (Release Planning)
  • 免费小说阅读小程序
  • 扑朔迷离的属性和特性【彻底弄清】
  • 前端技术周刊 2018-12-10:前端自动化测试
  • 前端面试之闭包
  • 深度学习中的信息论知识详解
  • 什么是Javascript函数节流?
  • 思考 CSS 架构
  • 找一份好的前端工作,起点很重要
  • puppet连载22:define用法
  • ​html.parser --- 简单的 HTML 和 XHTML 解析器​
  • ​一文看懂数据清洗:缺失值、异常值和重复值的处理
  • $.each()与$(selector).each()
  • (13):Silverlight 2 数据与通信之WebRequest
  • (C语言)输入自定义个数的整数,打印出最大值和最小值
  • (二)学习JVM —— 垃圾回收机制
  • (附源码)spring boot球鞋文化交流论坛 毕业设计 141436
  • (十八)三元表达式和列表解析
  • (四)TensorRT | 基于 GPU 端的 Python 推理
  • (转) RFS+AutoItLibrary测试web对话框
  • (转)iOS字体
  • ... 是什么 ?... 有什么用处?
  • .net mvc部分视图
  • .net 开发怎么实现前后端分离_前后端分离:分离式开发和一体式发布
  • @autowired注解作用_Spring Boot进阶教程——注解大全(建议收藏!)
  • @staticmethod和@classmethod的作用与区别