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

超级码力在线编程大赛初赛第1场-1-树木规划题解

目录

    • 题目描述
    • 示例
      • 输入
      • 输出
    • 说明
    • 分析
    • 代码
      • 动规
      • 贪心
    • 其他题目

在这里插入图片描述

题目描述

在一条直的马路上,有n棵树,每棵树有一个坐标,代表它们距离马路起点的距离。 如果每相邻的两棵树之间的间隔不小于d,那么我们认为这些树是美观的。 请计算出最少移除多少棵树,可以让这些树变得美观。
树木的棵树为n,1<=n<=1e5。 树木的坐标用trees[]表示,0<=trees[i]<=1e9。最小美观间隔为d,1<=d<=1e9。保证输入的坐标是排好序的,且两两不相同。

示例

输入

[1,2,3,5,6]
2

输出

2

说明

样例中,将位置2与6的树木移走,剩下[1,3,5],它们是美观的。

分析

我在一开始把这道题目当作了比较简单的动规。保证相邻两颗树的距离不小于d,这是个很明显的最优子问题结构。
设dp[i]为保留树木i作为最后一棵树木时留下树木的最大数量。遍历所有的j<i,当tree i与tree j的距离不低于d时,更新dp。状态转移方程为:

dp[i]=max(dp[i],dp[j]+1)

后面想到可以用贪心去解决。可以证明:最后一棵树一定可以保留,向前依次取距离满足条件的所有树即可。或是保留第一棵树,之后向后遍历,如果当前的树与上一棵选中的树之间的距离大于等于d,那么就保留这棵树,否则移除。

证明过程为:假设最终的最优解不可以包括最后一棵树,那么假设最优解中最后一棵树为I(n),倒数第二棵树为I(n-1)。则有trees[I(n)]-trees[I(n-1)]>=d。由于最后一棵树j一定满足trees[j]>trees[I(n)],因此一定有trees[j]-trees[I(n-1)]>d。所以不选择树I(n),而是选择j是完全可以的,因此保留最后一棵树一定可以得到最优解。以此类推,每次选择当前满足条件的最后面一棵树,问题解决。

显然动规算法的时间复杂度为O(N^2),贪心算法的时间复杂度为O(N)。

代码

动规

#include <vector>
#include <iostream>
using namespace std;
class Solution {
	public:
		int treePlanning(vector<int> &trees, int d) {
			// write your code here.
			int dp[trees.size()];
			for(int i=0; i<trees.size(); i++)
				dp[i]=1;
			for(int i=1; i<trees.size(); i++) {
				for(int j=0; j<i&&trees[i]-trees[j]>=d; j++) {
					dp[i]=max(dp[i],dp[j]+1);
				}
			}
			int max=0;
			for(int i=0; i<trees.size(); i++){
				cout<<dp[i]<<" ";
				if(dp[i]>max)
					max=dp[i];
			}
			return trees.size()-max;
		}
};
int main() {
	vector<int> v;
	v.push_back(0);
	v.push_back(2);
	v.push_back(3);
	v.push_back(5);
	v.push_back(6);
	v.push_back(9);
	v.push_back(10);
	v.push_back(13);
	v.push_back(14);
	v.push_back(15);
	Solution s;
	cout<<endl<<s.treePlanning(v,2);
	return 0;
}

贪心

class Solution {
	public:
		int treePlanning(vector<int> &trees, int d) {
			// write your code here.
			int count=1;
			int curr=trees.size()-1;
			while(1) {
				int j=curr-1;
				while(j>=0&&trees[curr]-trees[j]<d) {
					j--;
				}
				if(j<0)
					break;
				if(trees[curr]-trees[j]>=d)
					curr=j;
				count++;
			}
			return trees.size()-count;
		}
};

其他题目

超级码力在线编程大赛初赛第1场-2-正三角形拼接题解

超级码力在线编程大赛初赛第1场-4-对称前后缀题解

三道题目AC,喜提阿里t恤一件~

相关文章:

  • EXCHANGE系统的默认队列说明(转贴)
  • 超级码力在线编程大赛初赛第1场-2-正三角形拼接题解
  • 超级码力在线编程大赛初赛第1场-4-对称前后缀题解
  • C++程序设计:相邻数对
  • C++程序设计:字符阵列(三角形字符阵列图形的打印)
  • C++程序设计:相反数
  • C++程序设计:折叠方阵
  • C++程序设计:消除类游戏
  • MaxDSNSize 未设置
  • C++程序设计:图像旋转
  • C++程序设计:分解质因数
  • 设置NTFS权限以避免通过webshell遍历主机目录(原创)
  • C++程序设计:打印杨辉三角形
  • 如何安装一个安全的动网(转)
  • C++程序设计:字符图形输出(数字三角形)
  • 【Linux系统编程】快速查找errno错误码信息
  • 【译】理解JavaScript:new 关键字
  • Android单元测试 - 几个重要问题
  • ES6之路之模块详解
  • express + mock 让前后台并行开发
  • Hibernate最全面试题
  • Java 网络编程(2):UDP 的使用
  • java多线程
  • JDK 6和JDK 7中的substring()方法
  • macOS 中 shell 创建文件夹及文件并 VS Code 打开
  • SpriteKit 技巧之添加背景图片
  • WordPress 获取当前文章下的所有附件/获取指定ID文章的附件(图片、文件、视频)...
  • 动手做个聊天室,前端工程师百无聊赖的人生
  • 给第三方使用接口的 URL 签名实现
  • 记一次用 NodeJs 实现模拟登录的思路
  • 将回调地狱按在地上摩擦的Promise
  • 解决jsp引用其他项目时出现的 cannot be resolved to a type错误
  • 近期前端发展计划
  • 使用agvtool更改app version/build
  • 小程序 setData 学问多
  • 格斗健身潮牌24KiCK获近千万Pre-A轮融资,用户留存高达9个月 ...
  • 数据可视化之下发图实践
  • ​html.parser --- 简单的 HTML 和 XHTML 解析器​
  • #HarmonyOS:Web组件的使用
  • #中的引用型是什么意识_Java中四种引用有什么区别以及应用场景
  • (2)Java 简介
  • (Redis使用系列) Springboot 使用redis的List数据结构实现简单的排队功能场景 九
  • (附源码)ssm高校运动会管理系统 毕业设计 020419
  • (附源码)计算机毕业设计大学生兼职系统
  • (论文阅读30/100)Convolutional Pose Machines
  • (强烈推荐)移动端音视频从零到上手(上)
  • (转)如何上传第三方jar包至Maven私服让maven项目可以使用第三方jar包
  • (转载)Linux网络编程入门
  • ******IT公司面试题汇总+优秀技术博客汇总
  • .dwp和.webpart的区别
  • .NET CLR Hosting 简介
  • .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现
  • .NET Framework与.NET Framework SDK有什么不同?
  • .NET 简介:跨平台、开源、高性能的开发平台
  • .NET 指南:抽象化实现的基类