HDU 5125 序列型DP

【題目鏈接】
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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章