【线型DP】【LCS】UVA_10635 Prince and Princess
嘤嘤嘤,我又来了,刚A完就写,这个沙雕题有丶恶心、 ???时间4.11发现所有表情包都莫得了
题目:
In an n×n chessboard, Prince and Princess plays a game. The squares in the chessboard are numbered 1, 2, 3, . . . , n∗n, as shown below:

The Prince moves along the sequence: 1 –> 7 –> 5 –> 4 –> 8 –> 3 –> 9 (Black arrows), while the Princess moves along this sequence: 1 –> 4 –> 3 –> 5 > 6 –> 2 –> 8 –> 9 (White arrow). The King – their father, has just come. “Why move separately? You are brother and sister!” said the King, “Ignore some jumps and make sure that you’re always together.” For example, if the Prince ignores his 2nd, 3rd, 6th jump, he’ll follow the route: 1 –> 4 –> 8 –> 9. If the Princess ignores her 3rd, 4th, 5th, 6th jump, she’ll follow the same route: 1 –> 4 –> 8 –> 9, (The common route is shown in figure 3) thus satisfies the King, shown above. The King wants to know the longest route they can move together, could you tell him?
n×n的棋盘中,王子和公主玩游戏。棋盘上的方块编号
1 2 3 。 。 ,n ∗ n,如下所示:
王子站在方格1中,使p跳跃,最后达到方格n ∗ n。他最多只能进入一个广场
一旦。因此,如果我们使用xp表示他输入的第p个平方,则x1,x2,。 。 。 ,xp + 1都不同。注意
x1 = 1且xp + 1 = n * n公主做类似的事情–站在广场1,使q跳,最终达到平方n ∗ n。我们使用y1,y2,。 。 。 ,yq + 1表示序列,并且所有q +1个数字均为不同。下面的图2显示了一个3×3的正方形,这是Prince的可能路线,而Princess的路线则不同。王子按照以下顺序移动:1 –> 7 –> 5 –> 4 –> 8 –> 3 –> 9(黑色箭头),而公主按照以下顺序移动:1 –> 4 –> 3 –> 5> 6 –> 2 –> 8 –> 9(白色箭头)。国王–他们的父亲,刚来。 “为什么要分开移动?你是兄弟姐妹!”国王说,“应该忽略一些跳跃,并确保您一直在一起。”例如,如果王子忽略了他的第二,第三,第六跳,他将遵循以下路线:1 –> 4 –> 8 –>9.如果公主不理her她的第三,第四,第五,第六跳,她将遵循相同的路线:1 –> 4 –> 8 –>9因此,如图9所示,通用路线如图3所示。国王想你知道他们可以一起走的最长路线,你能告诉他吗?
输入值
输入的第一行包含一个整数t(1≤t≤10),其后是测试用例的数量。对于每种情况,第一行包含三个整数n,p,q(2≤n≤250,1≤p,q <n * n)。第二行包含[1]范围内的p + 1个不同的整数。 。 。 n * n],王子的序列。第三行在[1。范围内包含q + 1个不同的整数。 。 。 n * n],公主的顺序。
输出量
对于每个测试案例,请输出案例编号和最长路径的长度。
样本输入
1
3 6 7
1 7 5 4 8 3 9
1 4 3 5 6 2 8 9
样本输出
Case 1: 4
框架:
拿到这题第一反应——花里胡哨,前面王子公主一顿操作猛如虎,最后竟然就让我们求个最大公共上升子序列,抱着这样的想法,我带着老师上课写的优化过的O(n*n)LCIS模板以及仰天大笑的姿态提交了这道题,直接上代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;//数组别小了
const int maxn=*+,INF=0x3f3f3f3f;
int n,m,t,p,q,f[][maxn],a[maxn],b[maxn];
inline int read(){
int s=,w=;
char ch=getchar();
while(ch<''||ch>''){if(ch=='-')w=-;ch=getchar();}
while(ch>=''&&ch<='') s=s*+ch-'',ch=getchar();
return s*w;
}//朴素的快读
int main(){
freopen("a.in","r",stdin);
t=read();
int cnt=;
while(++cnt<=t){
n=read();
p=read();
q=read();
int maxmax=;//听说register能省点时间
for(register int i=;i<=n*n;i++){
f[][i]=f[][i]=a[i]=b[i]=;
}
for(register int i=;i<=p+;i++)a[i]=read();
for(register int i=;i<=q+;i++)b[i]=read();
for(register int i=;i<=p+;i++){
int ans=;//lcis模板
for(register int j=;j<=q+;j++){
f[i%][j]=f[(i-)%][j];//喜欢这样做滚动数组
if(a[i]>b[j]&&ans<f[i%][j])ans=f[i%][j];
if(a[i]==b[j])f[i%][j]=ans+;
maxmax=max(maxmax,f[i%][j]);
}//解释:因为lcis一定是从左或从上转移过来
//所以能用滚动数组节省时间空间
}
printf("Case %d: %d\n",cnt,maxmax);
}
}
然后结局很惨:

在这几个小时的时间里,我以为是某些地方时间超了那么一丢丢,于是从memset改到循环初始化,从cin改到快读,最后再压了压数组大小,喜提11连错
然后我才发现我被样例所蛊惑,这道题求得不是lcis,是lcs(很蠢),
但lcs和lcis都是n*n的时间,所以也不用看了,但为了矫正,还是上一下代码(是不是相当于给大家复习了一下lcs和lcis):
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;//数组别小了
const int maxn=*+,INF=0x3f3f3f3f;
int n,m,t,p,q,f[][maxn],a[maxn],b[maxn],ans;
inline int read(){
int s=,w=;
char ch=getchar();
while(ch<''||ch>''){if(ch=='-')w=-;ch=getchar();}
while(ch>=''&&ch<='') s=s*+ch-'',ch=getchar();
return s*w;
}//朴素的快读
int main(){
freopen("a.in","r",stdin);
t=read();
int cnt=;
while(++cnt<=t){
n=read();
p=read();
q=read();
int maxmax=0,k=0;//听说register能省点时间
for(register int i=;i<=n*n;i++){
k=!k;
f[k][i]=f[!k][i]=a[i]=b[i]=;
}
for(register int i=;i<=p+;i++)a[i]=read();
for(register int i=;i<=q+;i++)b[i]=read();
for(int i=;i<=p+;i++){
k=!k;//另一种滚动数组,用^k也行
for(int j=;j<=q+;j++){
if(a[i]==b[j])f[k][j]=f[!k][j-]+;//字符相同就从左上角转移
else f[k][j]=max(f[!k][j],f[k][j-]);//不相同就从上或左中的最大的转移
ans=max(ans,f[k][j]);
}
}
printf("Case %d: %d\n",cnt,ans);
}
}
时间4.9,开肝
后来我迫不得已查了下题解,发现这道题并不是用n*n效率的lcis模板,而是用nlogn的简化版先上代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<map>//map的库,当然可以不用map直接用数组对应
using namespace std;
const int maxn=*+,maxe=*+,INF=0x3f3f3f3f;
int n,m,t,p,q,f[maxe],a[maxn],b[maxn],low[maxn];
inline int read(){
int s=,w=;
char ch=getchar();
while(ch<''||ch>''){if(ch=='-')w=-;ch=getchar();}
while(ch>=''&&ch<='') s=s*+ch-'',ch=getchar();
return s*w;
}//朴素快读
int main(){
freopen("a.in","r",stdin);
t=read();
int cnt=;
while(++cnt<=t){
n=read();
p=read();
q=read();
int maxmax=;
memset(low,,sizeof(low));
map<int,int> mp;
for(register int i=;i<=p+;i++)a[i]=read(),mp[a[i]]=i;
int len=;//这里对第一组序列进行对应
for(register int i=;i<=q+;i++){
b[++len]=read();//如果第二组序列中出现了前一组序列的数的位置就加到数组里
if(mp.find(b[len])==mp.end())len--;//没有就删除
else b[len]=mp[b[len]];
}
//for(int i=1;i<=len;i++)cout<<b[i]<<" ";
int len1=;
low[]=b[];
for(register int i=;i<=len;i++){
if(low[len1]<b[i])low[++len1]=b[i];
else low[lower_bound(low+,low+len1+,b[i])-low]=b[i];
}//找一下新序列中最长上升子序列就是结果,想成友好城市保证顺序一致也行 printf("Case %d: %d\n",cnt,len1);
}
}
解释:
1.我们现行比较两个序列,因为要想求最长相等子序列,最后的子序列中肯定包含两个序列中的相等的字符,所以我们先取重,同时对第一组序列每一个字符进行编号,在输入第二组序列时一边去重一边把重复字符的对应填在新数组中,最后对新数组进行LIS,保证两个子序列的顺序相同
2.那LCS能用nlogn的时间写,那么我们还学原来那个n*n的干什么?在这里我们要注意,本体有一个条件:一个序列中每一个数都不同(题目里标红了),这样我们才可以用对应,而对两个相同的数我们就不能保证有两个不同的对应,所以只能用n*n的LCS。什么,你不知道两个相同的数我们不能保证有两个不同的对应?回去做潜伏者。什么,你说要用unique去重?那你错了没人救你。
总结:
这道题主要用了map中的对应,所以建议还是回去做做潜伏者巩固巩固
今晚写打鼹鼠的题解,争取写出线型动归和区间动归的模板,明天写多边形的题解
——2020/4/8~2020/4/9
【线型DP】【LCS】UVA_10635 Prince and Princess的更多相关文章
- uva 10635 - Prince and Princess(LCS)
题目连接:10635 - Prince and Princess 题目大意:给出n, m, k,求两个长度分别为m + 1 和 k + 1且由1~n * n组成的序列的最长公共子序列长的. 解题思路: ...
- 【线型DP模板】最上上升子序列(LIS),最长公共子序列(LCS),最长公共上升子序列(LCIS)
BEGIN LIS: 一个数的序列bi,当b1 < b2 < … < bS的时候,我们称这个序列是上升的.对于给定的一个序列(a1, a2, …, aN),我们可以得到一些上升的子序 ...
- Prince and princess——需要优化的DP
一个时间效率为o(nlogn)的算法求公共子序列的应用 Prince and princess 题目大意(已翻译 ) 在nxn的棋盘上,王子和公主玩游戏.棋盘上的正方形编号为1.2.3 ... n * ...
- UVA - 10635 Prince and Princess LCS转LIS
题目链接: http://bak.vjudge.net/problem/UVA-10635 Prince and Princess Time Limit: 3000MS 题意 给你两个数组,求他们的最 ...
- UVa10653.Prince and Princess
题目连接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- UVA 10653.Prince and Princess
题目 In an n * n chessboard, Prince and Princess plays a game. The squares in the chessboard are numbe ...
- 强连通+二分匹配(hdu4685 Prince and Princess)
Prince and Princess Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Othe ...
- 10635 - Prince and Princess
Problem D Prince and Princess Input: Standard Input Output: Standard Output Time Limit: 3 Seconds In ...
- Prince and Princess HDU - 4685(匹配 + 强连通)
Prince and Princess Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Othe ...
随机推荐
- Linux权限管理命令chown、chgrp、umask详解
命令chown详解 命令chown,所在路径为: 可以看到,这个命令的路径为:/usr/bin/chown ,所以它的执行权限是所有用户 命令的基本功能是改变文件或目录的所有者(只有root可以进行, ...
- [C#.NET 拾遗补漏]02:数组的几个小知识
阅读本文大概需要 1.5 分钟. 数组本身相对来说比较简单,能想到的可写的东西不多.但还是有一些知识点值得总结和知晓一 下.有的知识点,知不知道不重要,工作中用的时候搜索一下就可以了,毕竟实现一个功 ...
- 运维、python、docker视频教程
https://space.bilibili.com/97139894/?spm_id_from=333.788.b_7265636f5f6c697374.13 https://www.bilibil ...
- Swift 语法总结
1,用 var 定义变量 ,与js类似. let 用于定义常量,定义完后不能修改. var 用于定义变量,可以修改. swift可以自动识别属性类别. 2,使用 import 语句来引入任何的 Obj ...
- MongoDB知识点总结
一:MongoDB 概述 一.NoSQL 简介 1. 概念:NoSQL(Not Only SQL的缩写),指的是非关系型数据库,是对不同于传统的关系型数据库的数据库管理系统的统称.用于超大规模数 ...
- Python--循环--for && while
for循环示例:猜数字游戏 winning_number = 38 for i in range(3): guess_num = int(input("guess num:") ) ...
- log报错的原因解决
idea未装lombok的插件: 1.用快捷键Ctrl+Alt+S打开:Settings→Plugins→Browse repositories 2.输入lom后选择Install,安装插件 3.按照 ...
- BUAA_OO_2020_Unit3_总结博客
BUAA_OO_2020_Unit3_总结 2020年春季学期第十三周,OO第三单元落下帷幕,对这个单元的内容JML有了更深的理解,但也有了一些疑惑,下做总结: 一.JML语言以及工具链 经过课上JM ...
- 密码学数论基础部分总结之 有限域GF(p) Galois Fields
今天花了一下午的时间学习密码学的数论部分,下面将学到的内容进行一下总结,也算是加深记忆.我本身对密码学这方面比较感兴趣,而且本节出现了许多数学公式,使用刚刚学习的LaTex公式来呈现出来,练习练习,何 ...
- 《Java并发编程的艺术》 第9章 Java中的线程池
第9章 Java中的线程池 在开发过程中,合理地使用线程池能带来3个好处: 降低资源消耗.通过重复利用已创建的线程 降低线程创建和销毁造成的消耗. 提高响应速度.当任务到达时,任务可以不需要等到线程创 ...