JZOJ 4762. 【NOIP2016提高A组模拟9.7】千帆渡
题目
Description

Input

Output

Sample Input
5
1 4 2 5 1
4
1 1 2 4
Sample Output
2
1 4
Data Constraint

题解
好像挺显然地是一道动态规划题。
怎么设状态?
如果设f[i][j]f[i][j]f[i][j]为以a[i]a[i]a[i]和b[j]b[j]b[j]作为末尾的最大答案,这样必须保证a[i]=b[j]a[i]=b[j]a[i]=b[j],不仅会浪费很大的空间,而且转移起来也是O(n2m2)O(n^2m^2)O(n2m2)的,时间必然超限。
但如果设f[i][j]f[i][j]f[i][j]表示以a[k](k≤i)a[k](k≤i)a[k](k≤i)和b[j]b[j]b[j]作为末尾的最大大案,这样能有一些较为便捷的转移:
1、a[i]=b[j]a[i]=b[j]a[i]=b[j],f[i][j]=max(f[i−1][k])(k≤jf[i][j]=max(f[i-1][k])(k≤jf[i][j]=max(f[i−1][k])(k≤j且b[k]<b[j])b[k]<b[j])b[k]<b[j])
2、a[i]≠b[j]a[i]≠b[j]a[i]=b[j],f[i][j]=f[i−1][j]f[i][j]=f[i-1][j]f[i][j]=f[i−1][j]
怎么统计方案?
在存储最大长度的同时记录下由什么位置转移得到,最后从后往前倒推求值即可。
但这样是O(nm2)O(nm^2)O(nm2)的,还要优化。
很显然地,第一种情况的maxmaxmax可以用边做边维护。
a[i]=b[j]a[i]=b[j]a[i]=b[j],f[i][j]=max(f[i−1][k])(k≤jf[i][j]=max(f[i-1][k])(k≤jf[i][j]=max(f[i−1][k])(k≤j且b[k]<b[j])b[k]<b[j])b[k]<b[j]),
其实也就是f[i][j]=max(f[i−1][k])(k≤jf[i][j]=max(f[i-1][k])(k≤jf[i][j]=max(f[i−1][k])(k≤j且b[k]<a[i])b[k]<a[i])b[k]<a[i]),
那么就可以:
当b[j]<a[i]b[j]<a[i]b[j]<a[i]时,如果f[i−1][j]>maxf[i-1][j]>maxf[i−1][j]>max,则max=f[i−1][j]max=f[i-1][j]max=f[i−1][j].
于是这题就轻松地突破了!
代码
#include<cstdio>
#include<cstring>
using namespace std;
int a[5010],b[5010],ans[5010];
int f[5010][5010],g[5010][5010],h[5010][5010];
struct
{
int x,h;
}max[5010];
int main()
{
int n,m,i,j,k;
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%d",&a[i]);
scanf("%d",&m);
for(i=1;i<=m;i++) scanf("%d",&b[i]);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
if(a[i]!=b[j])
{
f[i][j]=f[i-1][j];
g[i][j]=g[i-1][j];
h[i][j]=h[i-1][j];
}
else
{
if(max[i-1].x+1>f[i][j])
{
f[i][j]=max[i-1].x+1;
g[i][j]=i-1;
h[i][j]=max[i-1].h;
}
}
if(b[j]<a[i])
{
if(f[i-1][j]>max[i-1].x)
{
max[i-1].x=f[i-1][j];
max[i-1].h=j;
}
}
}
int s=0;
for(i=1;i<=m;i++) if(f[n][i]>f[n][s]) s=i;;
printf("%d\n",f[n][s]);
int x=n,y=s;
s=f[n][s];
while(x!=0&&s>0)
{
ans[s]=b[y];
int x1=x;
x=g[x][y];
y=h[x1][y];
s--;
}
s=0;
while(ans[s+1]!=0) printf("%d ",ans[++s]);
return 0;
}

本文详细解析了JZOJ4762【NOIP2016提高A组模拟9.7】千帆渡的动态规划解题思路,包括状态设置、转移方程、优化方法及代码实现,适合对动态规划有兴趣的学习者。
691

被折叠的 条评论
为什么被折叠?



