【题目链接】
http://acm.hdu.edu.cn/showproblem.php?pid=5125
【解题报告】
求A的最长上升子序列,其中A中至多有M个元素可以被B中同位置元素替换。
考虑到数据范围只有1e3,所以完全可以用O(n^2)的方法来求LIS,但是由于有了B数组的加入,所以我们需要考虑Dp的状态要设置两个,一个是从上一个状态的a转移过来,一个是从上一个状态的b转移过来。
所以转移方程一共有2×2种情况,分类讨论列写转移方程即可。并没有太多难点,细心即可。
【参考代码】
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int dp[1000+100][2],m[1000+100][2],a[1100],b[1100];
int N,M;
void setdp( int i,int j,int Ki, int Kj )
{
dp[i][Ki]=dp[j][Kj]+1;
m[i][Ki]=m[j][Kj];
if( Ki==1 )m[i][Ki]+=1;
}
void solve()
{
memset( dp,0,sizeof dp );
memset( m,0,sizeof m);
// dp[1][0]=dp[1][1]=1;m[1][1]=1;
for( int i=1; i<=N; i++ )
for( int j=0; j<i; j++ )
{
if( a[i]>a[j] )if( dp[i][0]<dp[j][0]+1 || dp[j][0]+1==dp[i][0] && m[i][0]>m[j][0] )
setdp( i,j,0,0 );
if( a[i]>b[j] )if( dp[i][0]<dp[j][1]+1 || dp[i][0]==dp[j][1]+1 && m[i][0]>m[j][1] )
setdp( i,j,0,1 );
if( b[i]>a[j] )if( dp[i][1]<dp[j][0]+1 || dp[i][1]==dp[j][0]+1 && m[i][1]>m[j][0]+1 )
setdp(i,j,1,0);
if( b[i]>b[j] )if( dp[i][1]<dp[j][1]+1 || dp[i][1]==dp[j][1]+1 && m[i][1]>m[j][1]+1 )
setdp( i,j,1,1 );
}
}
int main()
{
int T; cin>>T;
while( T-- )
{
cin>>N>>M;
for( int i=1; i<=N; i++ ) cin>>a[i]>>b[i];
solve();
int ans=0;
for( int i=1; i<=N; i++ )
{
ans=( m[i][0]>M ) ? max( ans,dp[i][0]-m[i][0]+M ) : max( ans,dp[i][0] );
ans=( m[i][1]>M ) ? max( ans, dp[i][1]-m[i][1]+M ) : max( ans,dp[i][1] );
}
cout<<ans<<endl;
}
return 0;
}
博客介绍了如何解决HDU 5125题目,该题目要求找到序列A的最长上升子序列,允许最多M个元素被B中对应位置的元素替换。解题策略是使用动态规划(DP),考虑从A或B的前一个状态转移过来,总共有4种情况,列出相应的转移方程,强调了问题的复杂性和数据范围限制,以及解题需要注意的细节。
3964

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



