某DP题目3
题意:
一根数轴上有n只怪物,第i个怪物所在的位置为ai,另有m个特殊点,第i个特殊点所在的位置为bi。你可以对怪物进行移动,若两怪物相邻,那么你不能把他们分开,移动时要看作一个整体。你可以选择向左或向右移动,直到撞到怪物,移动的次数不限制。现在要求最大数量的呆在特殊点上的怪物。 n <= 100000,m <= 2000
分析:
做这题的时候真的非常烦躁,卡在描述状态很久,静下心来思考才能更好地领悟。
由于最终答案与特殊点密切相关,且特殊点是固定不变的,我们不妨以特殊点为基础作转移。接下来我们就可以分情况来考虑了:假设第i只怪兽在特殊点j的左边,那么就需要pos[j]-pos[i]只怪兽填充,即第i+1~i+pos[j]-pos[i]向左移动;反之亦然。
然后我就思考状态,发现无论怎么想,转移都涉及到左移和右移,会出现状态重叠的情况。
那么就要把左移和右移分开,使转移的时候不出现状态重叠的情况。我们令F[i]为前i只怪兽能到达的特殊点的最大数量,而且还带有限制,对于转移怪兽i的时候,怪兽i只能选择不动或者向左移动。那不是说怪兽可以左右移吗?是的,只是怪兽i的向右移是在怪兽i+1~n的转移中,将左右移分开了。这样F[i]所得到的方案必满足所有的怪兽小于等于第i只怪兽的位置pos[i],避免了状态的重叠,这在后面的转移当中至关重要。
那么要如何转移呢?
其实在上面的思考中,已经可以得到答案了。
对于F[i]的转移,只有两种:不动或者向左移动。转移是基于特殊点的,你的转移都是为了去占满更多的特殊点,分类讨论如何占满。
1、不动。枚举位置比怪兽i小的特殊点j,若要占据特殊点j,那么就需要i-(pos[i]-pos[j])~i-1的怪兽右移,转移方程即为:F[i] = max{F[i-(pos[i]-pos[j])-1]+1}。当然还需要注意怪兽连成一块的情况。
2、向左移动。枚举位置特殊点j,以及预处理出位置最大不超过特殊点j的怪兽p。若要占据特殊点j,那么i-p需大于等于pos[j]-pos[p],转移方程即为:F[i] = max{F[p]+1}。这里如果出现连成一块的情况的话,就需要判断第i只怪兽是否在块的最右端,否则,又会出现状态重叠的情况。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream> using namespace std; const int maxn = ;
const int maxm = ;
int n, m, a[maxn], b[maxm];
int belong[maxn], lef_block[maxn], rig_block[maxn], Bcnt;
int p[maxm], f[maxn]; void in()
{
scanf("%d %d", &n, &m);
for (int i = ; i <= n; ++i)
scanf("%d", &a[i]);
for (int i = ; i <= m; ++i)
scanf("%d", &b[i]);
} void prepare()
{
sort(a+, a+n+);
sort(b+, b+m+);
Bcnt = ;
for (int i = ; i <= n; ++i)
{
if (a[i] != a[i-]+ || i == )
{
belong[i] = ++Bcnt;
lef_block[Bcnt] = i;
}
else
belong[i] = Bcnt;
if (a[i+] != a[i]+)
rig_block[Bcnt] = i;
}
for (int i = ; i <= m; ++i)
{
p[i] = p[i-];
while (a[p[i]+] <= b[i])
p[i] ++;
}
} void dp()
{
f[] = ;
for (int i = ; i <= n; ++i)
{
f[i] = f[i-];
for (int j = ; j <= m; ++j){
if (b[j] <= a[i])
{
//part 1 : i don't move, others rig-move
if (i-(a[i]-b[j]) >= )
{
int t = lef_block[belong[i-(a[i]-b[j])]];
f[i] = max(f[t-]+, f[i]);
}
//part 2 : i lef-move
if (b[j]-a[p[j]] <= i-p[j] && rig_block[belong[i]] == i)
{
f[i] = max(f[p[j]]+, f[i]);
}
}
else
break ;
}
}
printf("%d\n", f[n]);
} void work()
{
prepare();
dp();
} int main()
{
freopen("a.in", "r", stdin);
freopen("a.out", "w", stdout);
in();
work();
return ;
}
某DP题目3的更多相关文章
- DP题目列表/弟屁专题
声明: 1.这份列表不是我原创的,放到这里便于自己浏览和查找题目. ※最近更新:Poj斜率优化题目 1180,2018,3709 列表一:经典题目题号:容易: 1018, 1050, 1083, 10 ...
- dp题目列表
此文转载别人,希望自己能够做完这些题目! 1.POJ动态规划题目列表 容易:1018, 1050, 1083, 1088, 1125, 1143, 1157, 1163, 1178, 1179, 11 ...
- dp题目
从别的地方看来,最近一直在啃DP,有个目标,更有动力了. 1.Robberies 连接 :http://acm.hdu.edu.cn/showproblem.php?pid=2955 背包; ...
- 插头DP题目泛做(为了对应WYD的课件)
题目1:BZOJ 1814 URAL 1519 Formula 1 题目大意:给定一个N*M的棋盘,上面有障碍格子.求一个经过所有非障碍格子形成的回路的数量. 插头DP入门题.记录连通分量. #inc ...
- 很好的一个dp题目 Codeforces Round #326 (Div. 2) D dp
http://codeforces.com/contest/588/problem/D 感觉吧,这道题让我做,我应该是不会做的... 题目大意:给出n,L,K.表示数组的长度为n,数组b的长度为L,定 ...
- 两道很好的dp题目【4.29考试】
A 问题描述: 对于一个排列,考虑相邻的两个元素,如果后面一个比前面一个大,表示这个位置是上升的,用I表示,反之这个位置是下降的,用D表示.如排列3,1,2,7,4,6,5可以表示为DIIDID. 现 ...
- 题目1453:Greedy Tino(dp题目)
题目链接:http://ac.jobdu.com/problem.php?pid=1453 详解链接:https://github.com/zpfbuaa/JobduInCPlusPlus 参考代码: ...
- 题目1452:搬寝室(dp题目)
题目链接:http://ac.jobdu.com/problem.php?pid=1452 详解链接:https://github.com/zpfbuaa/JobduInCPlusPlus 参考代码: ...
- 题目1042:Coincidence(最长公共子序列 dp题目)
题目链接:http://ac.jobdu.com/problem.php?pid=1042 详解链接:https://github.com/zpfbuaa/JobduInCPlusPlus 参考代码: ...
- 概率dp+期望dp 题目列表(一)
表示对概率和期望还不是很清楚定义. 目前暂时只知道概率正推,期望逆推,然后概率*某个数值=期望. 为什么期望是逆推的,例如你求到某一个点的概率我们可以求得,然后我们只要运用dp从1~n每次都加下去就好 ...
随机推荐
- TypeScript在node项目中的实践
TypeScript在node项目中的实践 TypeScript可以理解为是JavaScript的一个超集,也就是说涵盖了所有JavaScript的功能,并在之上有着自己独特的语法.最近的一个新项目开 ...
- vs2012 error c4996: 'fopen': This function or variable may be unsafe
1>------ 已启动生成: 项目: 20130925, 配置: Debug Win32 ------1> stdafx.cpp1>d:\code\20130925\201309 ...
- gpk-update-icon占用CPU及清除【原创】
发现服务器有个gpk-update-icon一直占用CPU进程 网上查看相关信息比较少. gpk-update-icon是gnome的更新图标进程 俩种处理方法: 1.杀掉gpk-update-ico ...
- java的loadrunner脚本案例
/* * LoadRunner Java script. (Build: 670) * * ״̬£º²¢·¢²âÊÔͨ¹ý * ²âÊÔÈË£ºÕÔС±ò * ÈÕÆÚ£º2013-09-2 ...
- [转载]FFmpeg完美入门[1] - FFmpeg介绍及安装
1 FFmpeg简介 FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件).它提供了录制.转换以及流化音视 频的完整解决方案.它包含了非常先 ...
- 创建一个简单的Maven工程
Maven的工程结构如下图所示: 大致来看,Maven的工程结构如下: 在创建maven工程时,可以通过骨架创建,也可以不通过骨架创建. 我们先用idea通过骨架创建一个Maven工程. 配置pom. ...
- mysql视图学习总结(转)
一.使用视图的理由是什么?1.安全性.一般是这样做的:创建一个视图,定义好该视图所操作的数据.之后将用户权限与视图绑定.这样的方式是使用到 了一个特性:grant语句可以针对视图进行授予权限.2.查询 ...
- Delphi根据字符串实例化对象
我们可以通过ClassRegistry单元的TClassRegistry类很轻松的根据字符串创建出对象. 下面是该类几个主要函数的说明: // 获取TClassRegistry自身的单例引用class ...
- HDU 1217 Arbitrage(Bellman-Ford判断负环+Floyd)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1217 题目大意:问你是否可以通过转换货币从中获利 如下面这组样例: USDollar 0.5 Brit ...
- 计算 Python (list or array) 相同索引元素相等的个数
上代码: a = [2, 3, 3, 1, 1, 3, 3, 3, 2, 1, 3, 1, 3, 2, 2, 2, 3, 1, 2, 3, 2, 3, 1, 1, 2, 1, 1, 1, 2, 2, ...