博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[USACO17JAN]Subsequence Reversal序列反转
阅读量:4960 次
发布时间:2019-06-12

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

题目描述

Farmer John is arranging his NN cows in a line to take a photo (1 \leq N \leq 501≤N≤50). The height of the iith cow in sequence is a(i)a(i), and Farmer John thinks it would make for an aesthetically pleasing photo if the cow lineup has a large increasing subsequence of cows by height.

FJ would like there to be a long increasing subsequence within his ordering of the cows. In order to ensure this, he allows himself initially to choose any subsequence and reverse its elements.

For example, if we had the list

1 6 2 3 4 3 5 3 4

We can reverse the chosen elements

1 6 2 3 4 3 5 3 4

^ ^ ^ ^
to get

1 4 2 3 4 3 3 5 6

^ ^ ^ ^
Observe how the subsequence being reversed ends up using the same indices as it initially occupied, leaving the other elements unchanged.

Please find the maximum possible length of an increasing subsequence, given that you can choose to reverse an arbitrary subsequence once.

FJ正在安排他的N头奶牛排成一队以拍照(1<=n<=50)。队列中的第i头奶牛的身高为a[i],并且FJ认为如果奶牛的身高序列中含有一个很长的不下降子序列的话,这会是一张很好的照片。

回忆一下,子序列是由牛序列中的一些元素a[i_1],a[i_2],.....a[i_k]组成的子集。(i_1<i_2<...<i_k) 如果a[i_1]<=a[i_2]<=a[i_3]<=......<=a[i_k]的话,我们就说这个序列是不下降的。

FJ想要在他的奶牛序列中包括一个长期增长的子序列(也就是很长的不下降子序列)。为了确保这一点,他允许自己在一开始选择任何子序列并逆转其元素。

观察这个子序列(上方英文)是如何反转并占据他们最初的相同的位置的,且其他元素保持不变。

在只能反转一次任意子序列的情况下,请找到不下降子序列的最大可能长度。

输入输出格式

输入格式:

The first line of input contains NN. The remaining NN lines contain a(1) \ldots a(N)a(1)…a(N), each an integer in the range 1 \ldots 501…50.

第一行一个整数N。

接下来N行包括N个整数a[1]...a[n],每行一个在1到50之间的整数。

输出格式:

Output the number of elements that can possibly form a longest increasing subsequence after reversing the contents of at most one subsequence.

输出反转一次任意子序列后所得到的不下降子序列的最大可能长度。

输入输出样例

输入样例#1:

9
1
2
3
9
5
6
8
7
4
输出样例#1:
9

解题报告:

很巧妙的思维题啊,一开始丝毫没有思路,瞟了一眼题解,看到一句话:交换一个序列相当于不相交的交换几个元素.因为这几个元素交换之后就相当于是交换了一个子序列
有了这句话的提示,问题就迎刃而解了.关键要做到交换的元素不能相交,其实只需要DP的顺序没问题即可,那么显然假设[L,R]已经解决了,那么交换的元素就强制只能在[L,R]之外.
下面正式开始DP,定义\(f[l][r][i][j]\)表示区间[l,r]间,值域在[i,j]间的最长上升子序列的长度,那么就转移就是交换和不交换的区别.
\(f[l][r][i][j]=Max(f[l+1][r][i][j]+(a[l]==i),f[l][r-1][i][j]+(a[r]==j))\)
\(f[l][r][i][j]=Max(f[l+1][r-1][i][j]+(a[l]==j)+(a[r]==i))\)
一式是不交换的转移,二式是交换的转移
注意:\(f[l][r][i-1][j]=f[l][r][i][j]\),\(f[l][r][i][j+1]=f[l][r][i][j]\)
注意值域是可以向两边扩展的

#include 
#include
#include
#include
#include
#include
#define RG register#define il inline#define iter iterator#define Max(a,b) ((a)>(b)?(a):(b))#define Min(a,b) ((a)<(b)?(a):(b))using namespace std;const int N=55;int n,a[N],f[N][N][N][N];void work(){ scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<=n;i++){ for(int j=1;j<=a[i];j++) for(int k=a[i];k<=50;k++) f[i][i][j][k]=1; } for(int k=2;k<=n;k++){ for(int l=1;l<=n;l++){ int r=l+k-1;if(r>n)break; for(int i=1;i<=50;i++){ for(int j=i;j<=50;j++){ f[l][r][i][j]=Max(f[l][r][i][j], Max(f[l+1][r][i][j]+(a[l]==i), f[l][r-1][i][j]+(a[r]==j))); f[l][r][i][j]=Max(f[l][r][i][j], f[l+1][r-1][i][j]+ (a[r]==i)+(a[l]==j)); f[l][r][i][j+1]= Max(f[l][r][i][j+1],f[l][r][i][j]); f[l][r][i-1][j]= Max(f[l][r][i-1][j],f[l][r][i][j]); } } for(int j=1;j<=50;j++) for(int i=j;i>=1;i--) f[l][r][i-1][j]=Max(f[l][r][i-1][j],f[l][r][i][j]); } } printf("%d\n",f[1][n][1][50]);}int main(){ work(); return 0;}

转载于:https://www.cnblogs.com/Yuzao/p/7441411.html

你可能感兴趣的文章
hiho_offer收割18_题解报告_差第四题
查看>>
AngularJs表单验证
查看>>
静态方法是否属于线程安全
查看>>
02号团队-团队任务3:每日立会(2018-12-05)
查看>>
SQLite移植手记1
查看>>
C# windows程序应用与JavaScript 程序交互实现例子
查看>>
HashMap详解
查看>>
js05-DOM对象二
查看>>
mariadb BINLOG_FORMAT = STATEMENT 异常
查看>>
C3P0 WARN: Establishing SSL connection without server's identity verification is not recommended
查看>>
iPhone在日本最牛,在中国输得最慘
查看>>
动态方法决议 和 消息转发
查看>>
js 基础拓展
查看>>
C#生成随机数
查看>>
Android应用程序与SurfaceFlinger服务的连接过程分析
查看>>
Java回顾之多线程
查看>>
sqlite
查看>>
机电行业如何进行信息化建设
查看>>
9、总线
查看>>
Git 笔记 - section 1
查看>>