BZOJ


题意:给出\(1\sim n\)的一个排列的一个最长上升子序列,求原排列可能的种类数。

\(n\leq 15\)。

\(n\)很小,参照HDU 4352这道题,我们直接把求\(LIS\)时的状态存下来做DP数组的状态。

状态就是那个单调递增的单调栈。每个数会有三种可能:没入过栈,现在在栈中,之前在栈中但是被替换掉了。

所以用一个\(n\)位三进制数表示单调栈的状态\(s\)。然后枚举状态\(s\),再枚举一个没出现过的数,很好转移。

转移时注意\(LIS\)长度不能超过\(k\),以及要能形成给定的\(LIS\)即可(现在加入的数如果在给定的\(LIS\)中,那它在\(LIS\)中的前一个数要出现过,后一个数没出现过)。

复杂度\(O(n3^n)\)。加点剪枝问题不大。

其实可以把非\(0\)的状态扔到一个queue里,不用\(3^n\)地for


//56872kb	1472ms
#include <cstdio>
#include <algorithm>
typedef long long LL;
const int N=20; int main()
{
static int A[N],id[N],pw[N],sta[N],lis[N],f[14348909]; int n,K; scanf("%d%d",&n,&K);
for(int i=1; i<=K; ++i) scanf("%d",&A[i]), id[--A[i]]=i;
pw[0]=1;
for(int i=1; i<=n; ++i) pw[i]=pw[i-1]*3; int ans=0;
f[0]=1, sta[A[0]=n]=1, sta[A[K+1]=n+1]=0;
for(int s=0,v; s+1<pw[n]; ++s)
if((v=f[s]))
{
int cnt=0,tot=0;
for(int i=0,tmp=s; i<n; ++i,tmp/=3)
tot+=((sta[i]=tmp%3)>0), sta[i]==1&&(lis[cnt++]=i);
if(tot==n) {ans+=v; continue;}//三进制啊...最后答案不只是f[pw[n]-1]
lis[cnt]=20;
for(int i=0; i<n; ++i)
if(!sta[i])
{
if(id[i] && (!sta[A[id[i]-1]]||sta[A[id[i]+1]])) continue;
int j=0;
while(lis[j]<i) ++j;
if(j==K) continue;//length>K
f[s+pw[i]+(j==cnt?0:pw[lis[j]])]+=v;//pw[lis[j]] not pw[j]..
}
}
printf("%d\n",ans); return 0;
}

BZOJ.3591.最长上升子序列(状压DP)的更多相关文章

  1. BZOJ 5161: 最长上升子序列 状压dp+查分

    好神啊 ~ 打表程序: #include <cstdio> #include <cstring> #include <algorithm> #define N 14 ...

  2. 【bzoj5161】最长上升子序列 状压dp+打表

    题目描述 现在有一个长度为n的随机排列,求它的最长上升子序列长度的期望. 为了避免精度误差,你只需要输出答案模998244353的余数. 输入 输入只包含一个正整数n.N<=28 输出 输出只包 ...

  3. bzoj5161 最长上升子序列 状压DP(DP 套 DP) + 打表

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=5161 题解 回顾一下以前用二分求 LIS 的方法:令 \(f[i]\) 表示长度为 \(i\) ...

  4. [BZOJ 1072] [SCOI2007] 排列perm 【状压DP】

    题目链接:BZOJ 1072 这道题使用 C++ STL 的 next_permutation() 函数直接暴力就可以AC .(使用 Set 判断是否重复) 代码如下: #include <io ...

  5. BZOJ 3195 [Jxoi2012]奇怪的道路 | 状压DP

    传送门 BZOJ 3195 题解 这是一道画风正常的状压DP题. 可以想到,\(dp[i][j][k]\)表示到第\(i\)个点.已经连了\(j\)条边,当前\([i - K, i]\)区间内的点的度 ...

  6. BZOJ 1087: [SCOI2005]互不侵犯King [状压DP]

    1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3336  Solved: 1936[Submit][ ...

  7. BZOJ 3446: [Usaco2014 Feb]Cow Decathlon( 状压dp )

    水状压dp. dp(x, s) = max{ dp( x - 1, s - {h} ) } + 奖励(假如拿到的) (h∈s). 时间复杂度O(n * 2^n) ------------------- ...

  8. BZOJ 2734 [HNOI2012]集合选数 (状压DP、时间复杂度分析)

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=2734 题解 嗯早就想写的题,昨天因为某些不可告人的原因(大雾)把这题写了,今天再来写题解 ...

  9. 【刷题】BZOJ 3591 最长上升子序列

    Description 给出1~n的一个排列的一个最长上升子序列,求原排列可能的种类数. Input 第一行一个整数n. 第二行一个整数k,表示最长上升子序列的长度. 第三行k个整数,表示这个最长上升 ...

随机推荐

  1. lightoj1234 打表技巧:分块打表

    /* 打不了那么大的表,所以只记录分块的信息即可 */ #include<bits/stdc++.h> using namespace std; #define maxn 1000005 ...

  2. PHP 方法,类与对象的相关函数学习

    1.function_exists function_exists(string)检测函数是否存在,string表示需要检测的函数名称(注意与property_exists,method_exists ...

  3. 一道面试题 vuex缺点?

    最近去面试的时候,面试官有一道题是让我阐述用vuex的优缺点,优点倒还好说,这个缺点还真没有认识到,有道友可以帮忙解惑嘛? 2 回答 慕标5265247 这种问题一般都有通用回答套路.一件挺好的东西, ...

  4. js中的“==”和“===”的区别

    简单来说: == 代表相同, ===代表严格相同, 为啥这么说呢, 这么理解: 当进行双等号比较时候: 先检查两个操作数数据类型,如果相同, 则进行===比较, 如果不同, 则愿意为你进行一次类型转换 ...

  5. 没有-jackson相关依赖会抛出如下异常--------在spring官方文档有解释

    <!--jackson相关依赖--><!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackso ...

  6. POJ 1064 Cable master (二分法+精度控制)

    Cable master Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 65358   Accepted: 13453 De ...

  7. CMake在Visual Studio下保持目录结构

    CMake在Visual Studio下保持目录结构 原理 主要通过CMAKE自带函数source_group来设定. 需要把add_executable()函数进行封装,包裹一层source_gro ...

  8. 安装好ubuntu 18.10之后,屏幕一直在自动旋转,怎么办?

    sudo apt-get install okular dia gimp Gparted sudo add-apt-repository universesudo apt install gnome- ...

  9. 标准I/O的缓冲

    标准I/O实现了三种类型的用户缓冲,并为开发者提供了接口,可以控制缓冲区类型和大小. 无缓冲(Unbuffered) 不执行用户缓冲.数据直接提交给内核.因为这种无缓冲模式不支持用户缓冲(用户缓冲一般 ...

  10. JSP基础知识➣语法整理(二)

    A.脚本程序 脚本程序可以包含任意量的Java语句.变量.方法或表达式,只要它们在脚本语言中是有效的. 脚本程序的语法格式:<% 代码片段 %>,但是不能包含文件的方法和变量的声明 B.J ...