链接:https://ac.nowcoder.com/acm/contest/3007/C
来源:牛客网

题目描述

现在你有 N 块矩形木板,第 i 块木板的尺寸是 Xi*Yi,你想用这些木板来玩汉诺塔的游戏。
我们知道玩汉诺塔游戏需要把若干木板按照上小下大的顺序堆叠在一起,但因为木板是矩形,所以有一个问题:
第 i 块木板能放在第 j 块木板上方当且仅当 Xi<Xj 且 Yi<Yj,于是你很可能没法把所有的木板按照一定的次序叠放起来。
你想把这些木板分为尽可能少的组,使得每组内的木板都能按照一定的次序叠放。
你需要给出任意一种合理的分组方案。
提醒:“任意”意味着你的答案不必和标准输出完全一致,只要正确即可。

输入描述:

第一行,一个正整数 N
接下来 N 行,每行两个正整数表示 Xi 和 Yi
对于所有的数据,1≤N≤100,000,1≤Xi,Yi≤N,Xi 互不相等且 Yi 互不相等

输出描述:

输出文件包含两行,第一行一个正整数,表示最少组数
第二行 N 个正整数,依次表示你的方案中每块木板分在了哪一组
组的编号必须是从 1 开始的连续整数

输入


输出

  

最长上升子序列的 贪心+二分法:O(nlogn) 

分析:要让一个序列具有最长上升子序列,其实就是保证子序列中的每个元素尽可能小,降低门槛,让后面的元素尽可能多进入该子序列

实现:定义一个最长子序列数组Array,以及当前长度Len,从头到尾维护数组a

a. a[i]>Array[i] (当前元素大于子序列结尾元素),则a[i]进入子序列:Array[++len] = a[i]

b. a[i]<=Array[i],这时对Array进行维护,把Array中比a[i]大的第一个元素替换成a[i](这样可以降低后面元素进入子序列的门槛。

c. 为了降低算法复杂度,因为Array是升序序列,所以用lower_bound查找Array中第一个大于等于a[i]的元素

官方题解:

将木板按照Xi从小到大排序,将这时的Yi数列记为Zi数列,则问题变成将Zi划分为尽可能少的若干组上升子序列
根据Dilworth定理,最小组数等于Zi的最长下降子序列长度
要求最长下降子序列的长度,我们有一种经典的二分优化dp的方法,在这里不再详述。 借助这种做法我们能给出一种构造方法,在求出最小组数的同时得出方案。
将状态数组的每个位置变为栈,用入栈操作代替修改元素操作,即可在求出组数的同时,用这些栈来完成对数列的划分。

这题跟以前一道dp题导弹拦截问题很像。

求最长下降子序列长度+二分

 #include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
const int INF=0x3f3f3f3f;
typedef long long LL;
const double eps =1e-;
const int mod=1e9+;
const int maxn=1e5+;
using namespace std; struct node
{
int x,y;
int id;
bool operator <(const node &a) const//小到大
{
return x<a.x;
}
}P[maxn]; int fa[maxn],st[maxn];
int cnt; int main()
{
#ifdef DEBUG
freopen("sample.txt","r",stdin);
#endif int n;
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d %d",&P[i].x,&P[i].y);
P[i].id=i;
}
sort(P+,P++n);
int cnt=;
for(int i=;i<=n;i++)
{
int L=,R=cnt;
while(L<=R)//二分查找st中第一个比P[i].y小的位置
{
int mid=(L+R)>>;
if(st[mid]<P[i].y)
R=mid-;
else if(st[mid]>P[i].y) L=mid+;
}
st[L]=P[i].y;//替换该位置的值(贪心)
if(L>cnt) cnt=L;//比st中所有都小,添到尾部
fa[P[i].id]=L;//它替换了st中谁的值,他就跟谁在同一个集合
}
printf("%d\n",cnt);
for(int i=;i<=n;i++)
printf(i==n?"%d\n":"%d ",fa[i]); return ;
}

求最长上升子序列长度+upper_bound()

 #include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
const int INF=0x3f3f3f3f;
typedef long long LL;
const double eps =1e-;
const int mod=1e9+;
const int maxn=1e5+;
using namespace std; struct node
{
int x,y;
int id;
bool operator <(const node &a) const//大到小
{
return x>a.x;
}
}P[maxn]; int fa[maxn],st[maxn];
int cnt; int main()
{
#ifdef DEBUG
freopen("sample.txt","r",stdin);
#endif int n;
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d %d",&P[i].x,&P[i].y);
P[i].id=i;
}
sort(P+,P++n);
int cnt=;
for(int i=;i<=n;i++)
{
int pos;
if(P[i].y>st[cnt]) pos=++cnt;//比st中所有都大,添到尾部
else pos=upper_bound(st+,st++cnt,P[i].y)-(st+)+;//下标别忘加1
st[pos]=P[i].y;//替换该位置的值(贪心)
fa[P[i].id]=pos;//它替换了st中谁的值,他就跟谁在同一个集合
}
printf("%d\n",cnt);
for(int i=;i<=n;i++)
printf(i==n?"%d\n":"%d ",fa[i]); return ;
}

-

汉诺塔(思维、DP思想)的更多相关文章

  1. hdu 1207 汉诺塔II (DP+递推)

    汉诺塔II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  2. BZOJ_1019_[SHOI2008]_汉诺塔_(DP)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1019 汉诺塔游戏,但是有移动优先级,在不违反原有规则的情况下,给定优先移动目标.求完成游戏所需 ...

  3. 【BZOJ 1019】 1019: [SHOI2008]汉诺塔 (DP?)

    1019: [SHOI2008]汉诺塔 Description 汉诺塔由三根柱子(分别用A B C表示)和n个大小互不相同的空心盘子组成.一开始n个盘子都摞在柱子A上,大的在下面,小的在上面,形成了一 ...

  4. 【ACwing 96】奇怪的汉诺塔——区间dp

    (题面来自ACwing) 汉诺塔问题,条件如下: 1.这里有A.B.C和D四座塔. 2.这里有n个圆盘,n的数量是恒定的. 3.每个圆盘的尺寸都不相同. 4.所有的圆盘在开始时都堆叠在塔A上,且圆盘尺 ...

  5. 2020牛客寒假算法基础集训营6 C 汉诺塔 (dp 最长下降子序列)

    https://ac.nowcoder.com/acm/contest/3007/C 将木板按照Xi从小到大排序,将这时的Yi数列记为Zi数列,则问题变成将Zi划分为尽可能少的若干组上升子序列. 根据 ...

  6. C语言数据结构----递归的应用(斐波拉契数列、汉诺塔、strlen的递归算法)

    本节主要说了递归的设计和算法实现,以及递归的基本例程斐波拉契数列.strlen的递归解法.汉诺塔和全排列递归算法. 一.递归的设计和实现 1.递归从实质上是一种数学的解决问题的思维,是一种分而治之的思 ...

  7. 四柱加强版汉诺塔HanoiTower----是甜蜜还是烦恼

    我想很多人第一次学习递归的时候,老师或者书本上可能会举汉诺塔的例子. 但是今天,我们讨论的重点不是简单的汉诺塔算法,而是三柱汉诺塔的延伸.先来看看经典的三柱汉诺塔. 一.三柱汉诺塔(Hanoi_Thr ...

  8. 汉诺塔 Hanoi Tower

    电影<猩球崛起>刚开始的时候,年轻的Caesar在玩一种很有意思的游戏,就是汉诺塔...... 汉诺塔源自一个古老的印度传说:在世界的中心贝拿勒斯的圣庙里,一块黄铜板上插着三支宝石针.印度 ...

  9. NOI-OJ 2.2 ID:6261 汉诺塔

    思路 汉诺塔是递归思想最经典的例子,通过递归不断缩小问题,将n个盘子的问题简化n-1个,直至1个. 三个盘子,分别为A:from,B:to,C:by(A为起点盘,B为目标盘,C为中转盘) 过程 将1- ...

  10. [递推]B. 【例题2】奇怪汉诺塔

    B . [ 例 题 2 ] 奇 怪 汉 诺 塔 B. [例题2]奇怪汉诺塔 B.[例题2]奇怪汉诺塔 题目描述 汉诺塔问题,条件如下: 这里有 A A A. B B B. C C C 和 D D D ...

随机推荐

  1. ie brower 点击用默认浏览器打开链接

    <script> function GetCurrentJumpUrl(){ var eleLink = document.getElementById('adLink'); if(ele ...

  2. 【C#】关于左移/右移运算符的使用

    吐槽先~为什么我的老师大学时候没教过我这东西  - -. 继续送栗子: 比如 “(1+2)<<3” 你们猜等于几~ Debug.Log((1+2)<<3)之后输出的是“24”. ...

  3. Anaconda下的 Jupyter Notebook 安装 多python环境

    装完 Anaconda 会自带一个pyhon环境   也会自带Jupyter Notebook   可以点击开始中的Jupyter Notebook 打开 浏览器 我这里是 3.x 想要装个2.7 的 ...

  4. POJ 2253:Frogger 求每一条路径最大值里面的最小值

    Frogger Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 31490   Accepted: 10150 Descrip ...

  5. 安装数据库Typical path for xclock: /usr/X11R6/bin/xclock 错误问题

    [oracle@localhost database]$ ./runInstaller Starting Oracle Universal Installer... Checking Temp spa ...

  6. 西门子 S7-200CN CPU 224CN EEPROM芯片

    拆下来了个 224CN 的EEPROM芯片

  7. C# 控制台应用程序从外部传参运行和调试

    参考:/*十有三博客*/ 新建一个用于演示的控制台应用程序项目,然后在Program.cs的入口Main方法里编写如下代码 foreach (var arg in args) { Console.Wr ...

  8. DCGAN增强图片数据集

    DCGAN增强图片数据集 1.Dependencies Python 3.6+ PyTorch 0.4.0 numpy 1.14.1, matplotlib 2.2.2, scipy 1.1.0 im ...

  9. svn全局设置过滤文件没有作用的解决办法

    svn全局设置过滤文件,网上教程文章很多, 都说了怎么配置,没有强调配置内容的格式 导致用惯了git的人,上手配置后,不起作用. 下面是我的配置内容: .classpath .project .set ...

  10. JuJu团队11月26号工作汇报

    JuJu团队11月26号工作汇报 JuJu   Scrum 团队成员 今日工作 剩余任务 困难 于达 对原始文本进行预处理, 并转换成可被julia读入的格式 完成预处理并用julia读入. 读入后按 ...