题解:P15301 [ROI 2012 Day 2] army 汗国军队
第一次见 DP 套 DP。
题意
求出有多少排列满足给定序列是它的一个 LIS。
Solution
看到数据范围,可以猜到复杂度里有个
LIS 可以用 DP 维护,这里我们维护数组
容易发现任意时刻,数组
原串拆成两部分:
这样我们就能用 DP 统计了,定义新的 DP
注意
代码
#include <iostream>
#include <cstdio>
using namespace std;
int read()
{
char c=getchar();
int f=1,x=0;
while(c<'0'||c>'9')
{
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
x=(x<<1)+(x<<3)+(c^'0');
c=getchar();
}
return x*f;
}
void print(int x)
{
if(x<0)
{
putchar('-');
x=-x;
}
if(x>9) print(x/10);
putchar(x%10+'0');
}
const int N=20;
int n,m,ans,f[N][N][1<<15];
bool a[N];
int main()
{
n=read();
m=read();
for(int i=1;i<=m;i++) a[read()]=true;
f[0][0][0]=1;
for(int i=1;i<=n;i++)
{
for(int j=0;j<i;j++)
{
for(int k=0;k<(1<<(i-1));k++)
{
int val=f[i-1][j][k];
if(!val) continue;
for(int x=0;x<i;x++)
{
if(a[i]&&x<j) continue;
int r=(k>>x),l=(k^(r<<x));
r^=(r&(-r));
r=(r<<1|1);
int y=j,s=(l|(r<<x));
if(a[i]) y=x+1;
else y+=(x<j);
f[i][y][s]+=val;
}
}
}
}
for(int i=0;i<=n;i++)
{
for(int j=0;j<(1<<n);j++)
{
int x=0;
for(int k=0;k<n;k++)
if((j&(1<<k))) x++;
if(x<=m) ans+=f[n][i][j];
}
}
print(ans);
return 0;
}