P1941 [NOIP2014 提高组] 飞扬的小鸟

news2024/12/26 21:04:06

代码部分前有一千六百字了

P1941 [NOIP2014 提高组] 飞扬的小鸟 考察对背包 dp 算法过程理解的透彻性。过程透彻性也是解决所有问题的关键(建立在算法已学的基础上)。

n , m n,m n,m 的范围足够我们 O ( n m ) O(nm) O(nm) 的遍历整个地图。设 f i , j f_{i,j} fi,j 表示到 ( i , j ) (i,j) (i,j) 格子时的最小点击数,考虑转移,共两种情况,分别是由前一个格子下移(即不动)或上移 x x x 次得到的。由于下移操作只有选或不选两种情况,我们可以把下移操作当作 01 背包来转移,即 f i j = min ⁡ ( f i , j , f i − 1 , j + d o w n [ i − 1 ] ) f_{i}{j}=\min(f_{i,j},f_{i-1,j+down[i-1]}) fij=min(fi,j,fi1,j+down[i1])

上移操作可以进行多次,如果对于每个格点上移操作分别进行 0 0 0 m / u p [ i ] m/up[i] m/up[i] 次的转移显然会超时,观察发现,单独对 f i , j f_{i,j} fi,j 进行上移操作的转移时, f i , j = min ⁡ ( f i , j , f i − 1 , j − u p [ i − 1 ] × x ) f_{i,j}=\min(f_{i,j},f_{i-1,j-up[i-1]\times x}) fi,j=min(fi,j,fi1,jup[i1]×x) f i , j = min ⁡ ( f i , j , min ⁡ ( f i − 1 , j − u p [ i − 1 ] , f i , j − u p [ i − 1 ] ) ) f_{i,j}=\min(f_{i,j},\min(f_{i-1,j-up[i-1]},f_{i,j-up[i-1]})) fi,j=min(fi,j,min(fi1,jup[i1],fi,jup[i1])) 的本质相同,而这正是完全背包算法过程的关键。

既然本质相同,那么转移方法便与完全背包保持一致性。注意到由于每个点不能同时选择上移和下移,而上移操作的转移用到了 f i , j − u p [ i − 1 ] f_{i,j-up[i-1]} fi,jup[i1] 即当前列某一位置的值,由上可知在对上移操作的转移中,使用到的 f i , j − u p [ i − 1 ] f_{i,j-up[i-1]} fi,jup[i1] 不能包含下移操作的更新,即使用到的 f i , j − u p [ i − 1 ] f_{i,j-up[i-1]} fi,jup[i1] 必须只包含上移操作的更新状态。

那么这里有两种方法,一种是将两次操作的转移分开,因为下移操作的转移需要用到的 f i − 1 , j − 1 + d o w n [ i − 1 ] f_{i-1,j-1+down[i-1]} fi1,j1+down[i1] 为前一列的值,且两种操作的转移都不会干扰前一列的值,所以可以先更新上移操作,再更新下移操作。

另一种是新增一维状态,设 f i , j , 0 / 1 f_{i,j,0/1} fi,j,0/1 表示 ( i , j ) (i,j) (i,j) 由上一列下移 /上移得到。思维量很小,但显然没有第一种方法简便。(我用的就是这种

注意上移时高度到了 m m m 将无法再上升,但和 0 0 0 处不同,冲到 m m m 高度不会使游戏结束。
所以转移时高度超过 m m m 的部分要参与 dp ,并转移至 m m m 那。

最后考虑柱子和是否能通关的判断。对于柱子,首先记得排序,可以在转移完毕之后将柱子所在处的 f f f 值再赋为 inf ⁡ \inf inf,也可以干脆在转移过程前标记,转移时就特判掉并跳过,当然也不可以不这么麻烦(猜对了我就这么敲的,调半天不对

通关判断就很简单了,转移完扫一遍当前列有没有解,到不了就退出,通过柱子数为当前柱子编号 − 1 -1 1,当前列过不了肯定说明有柱子(因为无论如何都可以一直按屏幕保持在 m m m 高度),当前柱子过不了自然过了的柱子就是编号 − 1 -1 1 了。

时间复杂度 O ( n m ) O(nm) O(nm)
空间复杂度 O ( n m ) O(nm) O(nm),可以滚掉一维,故为 O ( m ) O(m) O(m)

#include<bits/stdc++.h>
using namespace std;
int n,m,k,up[10005],down[10005],f[2][2005][2];
struct qh{
	int p,l,h;
	bool operator < (const qh &T)const {return p<T.p;}
}a[10005];
inline int Rd(){
	int s=0,w=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
	while (ch>='0'&&ch<='9') s=(s<<1)+(s<<3)+ch-'0',ch=getchar();
	return s*w;
}
int main(){
	n=Rd();m=Rd();k=Rd();
	for(int i=0;i<n;i++) up[i]=Rd(),down[i]=Rd();
	for(int i=1;i<=k;i++) a[i]=(qh){Rd(),Rd(),Rd()};
	sort(a+1,a+k+1);
//	for(int i=1;i<=k;i++) printf("%d %d %d\n",a[i].p,a[i].l,a[i].h);
	int z=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m*2;j++) f[i%2][j][0]=f[i%2][j][1]=1e9;
		for(int j=1;j<=m*2;j++){
			if(j+down[i-1]<=m) f[i%2][j][0]=min(f[(i-1)%2][j+down[i-1]][0],f[(i-1)%2][j+down[i-1]][1]);
			if(j-up[i-1]>0) f[i%2][j][1]=min(f[i%2][j-up[i-1]][1],min(f[(i-1)%2][j-up[i-1]][0],f[(i-1)%2][j-up[i-1]][1]))+1;
		}
		for(int j=m+1;j<=m*2;j++) f[i%2][m][1]=min(f[i%2][m][1],f[i%2][j][1]);
		if(a[z+1].p==i){
			z++;
			for(int j=1;j<=a[z].l;j++) f[i%2][j][0]=f[i%2][j][1]=1e9;
			for(int j=a[z].h;j<=m*2;j++) f[i%2][j][0]=f[i%2][j][1]=1e9;
//			printf("%d %d %d %d\n",z,a[z].p,a[z].l,a[z].h);
		}
		int mn=1e9;
		for(int j=1;j<=m;j++) mn=min(mn,min(f[i%2][j][0],f[i%2][j][1]));
//		for(int j=1;j<=m;j++) printf("%d %d ",f[i%2][j][0],f[i%2][j][1]);puts("");
		if(mn==1e9) return printf("0\n%d",z-1),0;
	}
	int ans=1e9;
	for(int i=1;i<=m;i++) ans=min(ans,min(f[n%2][i][0],f[n%2][i][1]));
	printf("1\n%d",ans);
	return 0;
}
/*
start coding:09:44 
finish debiuging:11:05
*/

附上题目:

[NOIP2014 提高组] 飞扬的小鸟

题目描述

Flappy Bird 是一款风靡一时的休闲手机游戏。玩家需要不断控制点击手机屏幕的频率来调节小鸟的飞行高度,让小鸟顺利通过画面右方的管道缝隙。如果小鸟一不小心撞到了水管或者掉在地上的话,便宣告失败。

为了简化问题,我们对游戏规则进行了简化和改编:

游戏界面是一个长为 n n n,高为 m m m 的二维平面,其中有 k k k 个管道(忽略管道的宽度)。

小鸟始终在游戏界面内移动。小鸟从游戏界面最左边任意整数高度位置出发,到达游戏界面最右边时,游戏完成。

小鸟每个单位时间沿横坐标方向右移的距离为 1 1 1,竖直移动的距离由玩家控制。如果点击屏幕,小鸟就会上升一定高度 x x x,每个单位时间可以点击多次,效果叠加;如果不点击屏幕,小鸟就会下降一定高度 y y y。小鸟位于横坐标方向不同位置时,上升的高度 x x x 和下降的高度 y y y 可能互不相同。

小鸟高度等于 0 0 0 或者小鸟碰到管道时,游戏失败。小鸟高度为 m m m 时,无法再上升。

现在,请你判断是否可以完成游戏。如果可以,输出最少点击屏幕数;否则,输出小鸟最多可以通过多少个管道缝隙。

输入格式

1 1 1 行有 3 3 3 个整数 n , m , k n, m, k n,m,k,分别表示游戏界面的长度,高度和水管的数量,每两个整数之间用一个空格隔开;

接下来的 n n n 行,每行 2 2 2 个用一个空格隔开的整数 x x x y y y,依次表示在横坐标位置 0 ∼ n − 1 0 \sim n-1 0n1 上玩家点击屏幕后,小鸟在下一位置上升的高度 x x x,以及在这个位置上玩家不点击屏幕时,小鸟在下一位置下降的高度 y y y

接下来 k k k 行,每行 3 3 3 个整数 p , l , h p,l,h p,l,h,每两个整数之间用一个空格隔开。每行表示一个管道,其中 p p p 表示管道的横坐标, l l l 表示此管道缝隙的下边沿高度, h h h 表示管道缝隙上边沿的高度(输入数据保证 p p p 各不相同,但不保证按照大小顺序给出)。

输出格式

共两行。

第一行,包含一个整数,如果可以成功完成游戏,则输出 1 1 1,否则输出 0 0 0

第二行,包含一个整数,如果第一行为 1 1 1,则输出成功完成游戏需要最少点击屏幕数,否则,输出小鸟最多可以通过多少个管道缝隙。

样例 #1

样例输入 #1

10 10 6 
3 9  
9 9  
1 2  
1 3  
1 2  
1 1  
2 1  
2 1  
1 6  
2 2  
1 2 7 
5 1 5 
6 3 5 
7 5 8 
8 7 9 
9 1 3

样例输出 #1

1
6

样例 #2

样例输入 #2

10 10 4 
1 2  
3 1  
2 2  
1 8  
1 8  
3 2  
2 1  
2 1  
2 2  
1 2  
1 0 2 
6 7 9 
9 1 4 
3 8 10

样例输出 #2

0
3

提示

【输入输出样例说明】

如下图所示,蓝色直线表示小鸟的飞行轨迹,红色直线表示管道。

【数据范围】

对于 30 % 30\% 30% 的数据: 5 ≤ n ≤ 10 , 5 ≤ m ≤ 10 , k = 0 5 \leq n \leq 10, 5 \leq m \leq 10, k=0 5n10,5m10,k=0,保证存在一组最优解使得同一单位时间最多点击屏幕 3 3 3 次;

对于 50 % 50\% 50% 的数据: 5 ≤ n ≤ 20 , 5 ≤ m ≤ 10 5 \leq n \leq 20, 5 \leq m \leq 10 5n20,5m10,保证存在一组最优解使得同一单位时间最多点击屏幕 3 3 3 次;

对于 70 % 70\% 70% 的数据: 5 ≤ n ≤ 1000 , 5 ≤ m ≤ 100 5 \leq n \leq 1000, 5 \leq m \leq 100 5n1000,5m100

对于 100 % 100\% 100% 的数据: 5 ≤ n ≤ 10000 5 \leq n \leq 10000 5n10000 5 ≤ m ≤ 1000 5 \leq m \leq 1000 5m1000 0 ≤ k < n 0 \leq k < n 0k<n 0 < x , y < m 0 < x,y < m 0<x,y<m 0 < p < n 0 < p < n 0<p<n 0 ≤ l < h ≤ m 0 \leq l < h \leq m 0l<hm l + 1 < h l + 1 < h l+1<h


start writing:19:00
finish the work:20:33

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/859901.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【金融量化】对企业进行估值的方法有哪些?

估值的方法有哪些&#xff1f; 如何对企业进行估值&#xff1f;有2个方法估算。 1 绝对估值法 它是一种定价模型&#xff0c;用于计算企业的内在价值。 比如说你可以根据公司近N年的现金流情况。借此去预测未来N年的现金流情况。所有的现金流数据都可以在年报上查询到。最后…

TypeScript使用npm安装报错问题

问题如图&#xff1a; 问题原因&#xff1a; 权限不足导致&#xff0c;可以输入如下命令&#xff1a; sudo npm install i -g typescript该命令会要求输入登录密码相关&#xff0c;稍等片刻&#xff0c;即可安装成功。检测安装的命令&#xff1a; tsc -v

LeetCode704. 二分查找

题目&#xff1a; LeetCode704. 二分查找 描述&#xff1a; 给定一个 n 个元素有序的&#xff08;升序&#xff09;整型数组 nums 和一个目标值 target &#xff0c;写一个函数搜索 nums 中的 target&#xff0c;如果目标值存在返回下标&#xff0c;否则返回 -1。 思路&#x…

leetcode59. 螺旋矩阵 II

题目&#xff1a;leetcode59. 螺旋矩阵 II 描述&#xff1a; 给你一个正整数 n &#xff0c;生成一个包含 1 到 n2 所有元素&#xff0c;且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 思路&#xff1a; 代码&#xff1a; public class Solution {public int[][…

小红书引流 推荐机制总结

大家好&#xff0c;我是网媒智星&#xff0c;今天跟大家分享一下小红书运营的方法&#xff0c;小红书推荐机制是怎样的呢&#xff1f; 小红书的推荐机制是怎样的&#xff1f;对于用户来说&#xff0c;小红书不仅是一个网络社区&#xff0c;也是一个共享平台。而对于品牌方和商家…

8月10日上课内容 Tomacat部署及优化

tomcat 开放源代码的web应用服务器。基于java代码开发的。 Tomcat介绍 tomcat就是处理动态请求和基于java代码的页面开发 可以在html当中写入java代码&#xff0c;tomcat可以解析html页面当中的java,执行动态请求&#xff0c;动态页面。缺点是机制有问题:不对tomcat进行优化&…

【笔记】树状数组

【笔记】树状数组 目录 简介引入1. 直接暴力2. 维护前缀和数组总结 定义前置知识&#xff1a; lowbit ⁡ \operatorname{lowbit} lowbit 操作区间的表示方法操作单点修改前缀和查询任意区间查询 例题1: 单点修改&#xff0c;区间查询例题2: 区间修改&#xff0c;单点查询例题3:…

UDP简介

UDP 1. UDP格式2. UDP特点3. 差错检验 1. UDP格式 16位UDP长度&#xff0c;表示整个数据报&#xff08;UDP首部UDP数据&#xff09;的最大长度&#xff1b; 如果校验和出错&#xff0c;就会直接丢弃; 2. UDP特点 无连接: 知道对端的IP和端口号就直接进行传输&#xff0c;不需…

用Python编写的小游戏:探索游戏世界的乐趣

探索开始 引言&#xff1a;第一部分&#xff1a;猜数字游戏代码案例1&#xff1a; 第二部分&#xff1a;石头剪刀布游戏代码案例2&#xff1a; 第三部分&#xff1a;迷宫游戏代码案例3&#xff1a; 总结&#xff1a; 引言&#xff1a; Python是一种简单易学的编程语言&#xf…

Centos7单机部署ElasticSearch

Centos7单机部署ElasticSearch 引言 Elasticsearch是一种广泛使用的开源搜索引擎&#xff0c;专门为分布式环境设计&#xff0c;但也可以在单机上运行。它使存储、搜索和分析大量数据变得更加容易和高效。此教程将引导你通过在Centos7上单机部署Elasticsearch&#xff0c;涵盖…

【JasperReports笔记01】Jasper Studio报表开发工具的安装以及使用Java填充模板文件内容

这篇文章&#xff0c;主要介绍如何安装Jasper Studio报表开发工具以及使用Java填充模板文件内容。 目录 一、安装Jasper Studio工具 1.1、下载报表开发工具 1.2、工具界面介绍 &#xff08;1&#xff09;启动工具 &#xff08;2&#xff09;创建项目 二、制作Jasper模板文…

CC++内存管理

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;那个传说中的man的主页 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;题目大解析2 目录 &#x1f449;&#x1f3fb;c内存管理方式new/delete 操作内置类型new和delete操…

不看太后悔了!呕心沥血总结JVM!

一、JVM 简介 JVM 是 Java Virtual Machine 的简称&#xff0c;意为 Java虚拟机。虚拟机是指通过软件模拟的具有完整硬件功能的、运行在一个完全隔离的环境中的完整计算机系统。 常见的虚拟机&#xff1a;JVM、VMwave、Virtual Box。 JVM 和其他两个虚拟机的区别&#xff1a; …

[HDLBits] Mt2015 q4b

Circuit B can be described by the following simulation waveform: Implement this circuit. module top_module ( input x, input y, output z );//001 100 010 111assign z(xy); endmodule

wordpress数据表中标签和分类如何区分?

wordpress中标签和分类是什么关系怎么区分&#xff1f;最后有一个群的网友告诉了我文章ID和标签ID的关系是放在了wp_term_relationships表中&#xff0c;然后我百度了下这个表的结构和相关介绍&#xff0c;发现果然如此&#xff0c;先把文章保存起来&#xff1a; wp_term_rela…

数据结构——空间复杂度

3.空间复杂度 空间复杂度也是一个数学表达式&#xff0c;是对一个算法在运行过程中临时占用存储空间大小的量度 。 空间复杂度不是程序占用了多少bytes的空间&#xff0c;因为这个也没太大意义&#xff0c;所以空间复杂度算的是变量的个数。 空间复杂度计算规则基本跟实践复杂…

基于SLAM的规划算法仿真复现|SLAM|智能规划

图片来自百度百科 前言 那么这里博主先安利一些干货满满的专栏了&#xff01; 首先是博主的高质量博客的汇总&#xff0c;这个专栏里面的博客&#xff0c;都是博主最最用心写的一部分&#xff0c;干货满满&#xff0c;希望对大家有帮助。 高质量博客汇总https://blog.csdn.n…

getchar()清空缓冲区剩余的空格回车等转义字符

getchar()清空缓冲区剩余的空格回车等转义字符 多次使用scanf输入字符会出现以下错误&#xff1a; #include <stdio.h> int main() {char a,b,c,d,e,f;printf("input character a,b\n");scanf("%c,%c",&a,&b);printf("a %c,b %c\n&…

【字节跳动青训营】后端笔记整理-1 | Go语言入门指南:基础语法和常用特性解析

**本人是第六届字节跳动青训营&#xff08;后端组&#xff09;的成员。本文由博主本人整理自该营的日常学习实践&#xff0c;首发于稀土掘金&#xff1a;&#x1f517;Go语言入门指南&#xff1a;基础语法和常用特性解析 | 青训营 本文主要梳理自第六届字节跳动青训营&#xff…

C++-排序

文章目录 常数操作时间复杂度空间复杂度O(N^2) O(1) 数据情况发生变化不影响流程 选择排序冒泡排序使用抑或运算提取出不为零的数最右边的1 1. 实现两个变量交换值2. 数组中一种数字出现奇数次,other是偶数次,找到那一种数字3. 数组中有两种数字出现奇数次,other是偶数次,找到那…