题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5125
题解:
这个题dp[i][0],dp[i][1]数组分别记录在第i个位置取a[i]和b[i]时可以取到最长上升子序列的长度,然后开一个m[i][0]和m[i][1]分别表示取到第i个位置时最少的交换次数.然后进行4次比较,最后取最大值的时候非常巧妙,如果m[i][0]>M,那么证明这个序列里面多了 m[i][0]-M 个数,所以要减掉这么多个数.
蒟蒻感觉别人好强啊....
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include <queue> using namespace std; const int N = 1005; int a[N],b[N],dp[N][2],m[N][2]; int main() { int tcase; scanf("%d",&tcase); while(tcase--){ int n,M; scanf("%d%d",&n,&M); for(int i=1;i<=n;i++){ scanf("%d%d",&a[i],&b[i]); } memset(m,0,sizeof(m)); memset(dp,0,sizeof(dp)); dp[1][1] = dp[1][0]=m[1][1] =1; for(int i=2;i<=n;i++){ dp[i][1]=dp[i][0] = m[i][1] =1; for(int j=1;j<i;j++){ if(a[i]>a[j]){ if(dp[i][0]<dp[j][0]+1||dp[i][0]==dp[j][0]+1&&m[i][0]>m[j][0]){ dp[i][0] = dp[j][0]+1; m[i][0] = m[j][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]){ dp[i][0] = dp[j][1]+1; m[i][0] = m[j][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){ dp[i][1] = dp[j][0]+1; m[i][1] = m[j][0]+1; } }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){ dp[i][1] = dp[j][1]+1; m[i][1] = m[j][1]+1; } } } } int MAX = 0; for(int i=1;i<=n;i++){ if(m[i][0]<=M) MAX = max(dp[i][0],MAX); else MAX = max(dp[i][0]-m[i][0]+M,MAX); if(m[i][1]<=M) MAX = max(dp[i][1],MAX); else MAX = max(dp[i][1]-m[i][1]+M,MAX); } printf("%d ",MAX); } return 0; }