题意:
有N个人,每个人有ai、bi两个球,可以用魔法交换ai和bi,每次交换消耗一点魔力值。现在有m点魔力值,问你最终得到的a的最长上升序列是多少,魔力值不能小于0.
解法:
dp[i][j][k]:
i:代表当前的位置
j:代表当前取a或是取b (0代表取a,1代表取b)
k:当k==0时,代表当前的最长序列,k==1,代表当前已使用的魔法值。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
int dp[1000+100][4][4];
struct node
{
int a,b;
}p[1000+100];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
memset(dp,0,sizeof(dp));
for(int i=0;i<=n;i++)
{
for(int j=0;j<2;j++)
{
dp[i][j][0]=1;
dp[i][j][1]=0;
}
}
dp[0][1][1]=1;
dp[0][0][1]=0;
for(int i=0;i<n;i++)
{
scanf("%d%d",&p[i].a,&p[i].b);
}
int ans=-1;
/*
dp[i][j][k]:
i:代表当前的位置
j:代表当前取a或是取b (0代表取a,1代表取b)
k:当k==0时,代表当前的最长序列,k==1,代表当前已使用的魔法值。
*/
for(int i=0;i<n;i++)
{
for(int j=0;j<i;j++)
{
if(p[i].a>p[j].a&&dp[i][0][0]<dp[j][0][0]+1)
{
dp[i][0][0]=max(dp[j][0][0]+1,dp[i][0][0]);
dp[i][0][1]=dp[j][0][1];
}
if(p[i].a>p[j].b&&dp[i][0][0]<dp[j][1][0]+1)
{
dp[i][0][0]=max(dp[j][1][0]+1,dp[i][0][0]);
dp[i][0][1]=dp[j][1][1];
}
if(p[i].b>p[j].a&&dp[i][1][0]<dp[j][0][0]+1)
{
dp[i][1][0]=max(dp[j][0][0]+1,dp[i][1][0]);
dp[i][1][1]=dp[j][0][1]+1;
}
if(p[i].b>p[j].b&&dp[i][1][0]<dp[j][1][0]+1)
{
dp[i][1][0]=max(dp[j][1][0]+1,dp[i][1][0]);
dp[i][1][1]=dp[j][1][1]+1;
}
}
if(dp[i][0][1]<=m)
ans=max(ans,dp[i][0][0]);
if(dp[i][1][1]<=m)
ans=max(ans,dp[i][1][0]);
}
printf("%d\n",ans);
}
return 0;
}