https://odzkskevi.qnssl.com/3699857ff0a17d77d1099699cdf4da13?v=1490503337
比较丑的做法
第一维滚动数组,dp【0】【i】【j】 是指上一层,以i为起点,j为终点的情况数,
#include<bits/stdc++.h>
using namespace std;
long long int dp[2][2005][2005],mo=2147483647;
int main()
{
int n,i,j,k,a[2005];
scanf("%d",&n);
for(i=0;i<=n;i++)
scanf("%d",&a[i]);
if(a[0]>a[1])
{
a[1]^=a[0]^=a[1]^=a[0];
}
dp[0][a[0]][a[1]]=1;
for(i=2;i<=n;i++)
{
if(a[i]>a[i-1])
{
for(j=1;j<=a[i-1];j++)
{
dp[1][j][a[i]]+=dp[0][j][a[i-1]];
dp[1][j][a[i]]%=mo;
}
for(j=a[i-1]+1;j<=a[i];j++)
{
dp[1][a[i-1]][a[i]]+=dp[0][a[i-1]][j];
dp[1][a[i-1]][a[i]]%=mo;
}
for(j=a[i]+1;j<=n+1;j++)
{
dp[1][a[i-1]][a[i]]+=dp[0][a[i-1]][j];
dp[1][a[i-1]][a[i]]%=mo;
dp[1][a[i]][j]+=dp[0][a[i-1]][j];
dp[1][a[i]][j]%=mo;
}
}
else
{
for(j=1;j<=a[i];j++)
{
dp[1][j][a[i]]+=dp[0][j][a[i-1]];
dp[1][j][a[i]]%=mo;
dp[1][a[i]][a[i-1]]+=dp[0][j][a[i-1]];
dp[1][a[i]][a[i-1]]%mo;
}
for(j=a[i]+1;j<=a[i-1];j++)
{
dp[1][a[i]][a[i-1]]+=dp[0][j][a[i-1]];
dp[1][a[i]][a[i-1]]%=mo;
}
for(j=a[i-1]+1;j<=n+1;j++)
{
dp[1][a[i]][j]+=dp[0][a[i-1]][j];
dp[1][a[i]][j]%=mo;
}
}
for(j=1;j<=n+1;j++)
{
dp[0][a[i-1]][j]=dp[0][j][a[i-1]]=0;
}
for(j=1;j<=n+1;j++)
{
dp[0][a[i]][j]=dp[1][a[i]][j];
dp[0][j][a[i]]=dp[1][j][a[i]];
dp[1][a[i]][j]=dp[1][j][a[i]]=0;
}
}
long long int ans=0;
for(i=1;i<=n+1;i++)
{
ans+=(dp[0][a[n]][i]+dp[0][i][a[n]]);
ans%=mo;
}
printf("%lld\n",ans);
return 0;
}其实dp数组值非零时的 i 和 j 里一定有i==a【k-1】或j==a【k-1】(a是题目给的已知序列),下面的求法就是根据这个的改进
比较优雅的做法。。。
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<map>
#include<vector>
#include<math.h>
using namespace std;
long long int dp[2][2005],ans,mo=(1<<31)-1;
int main()
{
int l,r,i,n,a[2005],j;
scanf("%d",&n);
for(i=1;i<=n+1;i++)
scanf("%d",&a[i]);
dp[0][a[1]]=1;
for(i=2;i<=n+1;i++)
{
for(j=1;j<=n+1;j++)
{
l=min(j,a[i-1]),r=max(j,a[i-1]);
if(l<a[i])
{
dp[1][l]+=dp[0][j];
dp[1][l]%=mo;
}
if(r>a[i])
{
dp[1][r]+=dp[0][j];
dp[1][r]%=mo;
}
}
for(j=1;j<=n+1;j++)
{
dp[0][j]=dp[1][j];
dp[1][j]=0;
}
}
ans=0;
for(i=1;i<=n+1;i++)
{
ans+=dp[0][i];
ans%=mo;
}
printf("%lld\n",ans);
return 0;
}优雅永远是别人的

本文对比了两种不同的动态规划解法来解决特定问题:一种较为复杂的方法使用三维滚动数组;另一种更为简洁优雅的方法则通过优化状态转移方程,显著减少了所需的状态数量。这两种方法都用于计算一系列数字中特定条件下的子序列数目。
1010

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



