博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
P1107 [BJWC2008]雷涛的小猫
阅读量:5424 次
发布时间:2019-06-15

本文共 2102 字,大约阅读时间需要 7 分钟。

题目描述

雷涛同学非常的有爱心,在他的宿舍里,养着一只因为受伤被救助的小猫(当然,这样的行为是违反学生宿舍管理条例的)。在他的照顾下,小猫很快恢复了健康,并且愈发的活泼可爱了。

可是有一天,雷涛下课回到寝室,却发现小猫不见了!经过一番寻找,才发现她正趴在阳台上对窗外的柿子树发呆…

在北京大学的校园里,有许多柿子树,在雷涛所在的宿舍楼前,就有N棵。并且这N棵柿子树每棵的高度都是H。冬天的寒冷渐渐笼罩了大地,树上的叶子渐渐掉光了,只剩下一个个黄澄澄的柿子,看着非常喜人。而雷涛的小猫恰好非常的爱吃柿子,看着窗外树上的柿子,她十分眼馋,于是决定利用自己敏捷的跳跃能力跳到树上去吃柿子。

小猫可以从宿舍的阳台上跳到窗外任意一棵柿子树的树顶。之后,她每次都可以在当前位置沿着当前所在的柿子树向下跳1单位距离。当然,小猫的能力远不止如此,她还可以在树之间跳跃。每次她都可以从当前这棵树跳到另外的任意一棵,在这个过程中,她的高度会下降Delta单位距离。每个时刻,只要她所在的位置有柿子,她就可以吃掉。整个“吃柿子行动”一直到小猫落到地面上为止。

雷涛调查了所有柿子树上柿子的生长情况。他很想知道,小猫从阳台出发,最多能吃到多少柿子?他知道写一个程序可以很容易的解决这个问题,但是他现在懒于写任何代码。于是,现在你的任务就是帮助雷涛写一个这样的程序。

图为N=3,H=10,Delta=2的一个例子。小猫按照图示路线进行跳跃,可以吃到最多的8个柿子

输入输出格式

输入格式:

第一行有三个以空格分隔的整数,分别代表N,H,Delta

接下来的N行,每行第一个整数为Ni,代表第i棵树上的柿子数量。

接下来是Ni个整数,每个整数Tij代表第i棵柿子树的Tij高度上长有一个柿子。

输出格式:

一个整数,即小猫最多吃到的柿子数。

输入输出样例

输入样例#1: 
3 10 23 1 4 106 3 5 9 7 8 95 4 5 3 6 9
输出样例#1: 
8

说明

1≤N,H≤2000

0≤Ni≤50000

1≤Delta≤N,1≤Tij≤H

输入文件大小不大于40960KB

来源 Excalibur, 2008

 

Solution:

  本题贪心优化dp(话说今天分班考试,炸穿了,作文没写完~物理啥公式都不会~凉凉)。

  很容易想到本题dp思路,既然和$N,H$有关,那么状态就这俩东西咯,定义$f[i][j]$表示在第$j$棵树的$i$高度能得到的最多果子数,由于每次跳就两种情况,状态转移方程就呼之欲出了:$f[i][j]=max(f[i-1][j],f[i-Delta][k]),k!=j$。

  但是一个问题是这样的dp是$O(N^2H)$的转移,显然爆掉。

  发现转移时$f[i-Delta][k]$的最大值是可以确定的,贪心的想到,选的话肯定是从$i-Delta$高度下最多的那棵树转移过来,于是维护$g[i]$表示$i$高度下最多的果子数,每次转移完时维护一下$g$。注意$k!=j$,每次转移先使$f[i][j]=f[i-1][j]$,就不用担心从同一棵树的$i-Delta$转移过来的情况了。

  目标状态$g[H]$,时间复杂度$O(NH)$,稳妥>._.<。

代码:

/*Code by 520 -- 8.29*/#include
#define il inline#define ll long long#define RE register#define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)#define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)using namespace std;const int N=5005;int n,h,d,a[N][N],f[N][N],g[N],x;int gi(){ int a=0;char x=getchar(); while(x<'0'||x>'9')x=getchar(); while(x>='0'&&x<='9')a=(a<<3)+(a<<1)+(x^48),x=getchar(); return a;}int main(){ n=gi(),h=gi(),d=gi(); For(i,1,n) { x=gi(); For(j,1,x) a[i][gi()]++; } For(i,1,h){ For(j,1,n) f[i][j]=f[i-1][j]+a[j][i]; if(i>d) For(j,1,n) f[i][j]=max(f[i][j],g[i-d]+a[j][i]); For(j,1,n) g[i]=max(f[i][j],g[i]); } cout<

 

转载于:https://www.cnblogs.com/five20/p/9557207.html

你可能感兴趣的文章
p38 二、八、十六进制的对应关系
查看>>
Oracle 学习----:创建表(主键自增)
查看>>
XV Open Cup named after E.V. Pankratiev. GP of Central Europe (AMPPZ-2014)--J.Cave
查看>>
Effective C++笔记——day01
查看>>
Leetcode题解(32)
查看>>
git删除文件
查看>>
P4302 [SCOI2003]字符串折叠
查看>>
神秘的程序员
查看>>
jS 中创建对象:
查看>>
jeecms系统使用介绍——jeecms中的内容、栏目、模型之间的关系
查看>>
UWP 设置桌面壁纸、锁屏图片
查看>>
Vue.2.0.5-事件处理器
查看>>
性能测试常用概念及计算公式
查看>>
python接口自动化测试五:乱码、警告、错误处理
查看>>
分页查询的一个帮助类
查看>>
svn批量的添加ignore
查看>>
zless轻量级样式框架
查看>>
where 1=0的含义
查看>>
ZeroMQ接口函数之 :zmq_term - 终结ZMQ环境上下文(context)
查看>>
【杂谈】用了几千年的就是有用的吗?
查看>>