开三维dp,第一维是时间,第二维表示在哪颗树下(0表示第一棵,1表示第二棵),第三维表示用了几次移动的机会。
然后状态转移方程
if(num[i]==1){
dp[i][0][j] = max(dp[i][0][j],dp[i-1][0][j]+1);
if(j!=w)
dp[i][0][j] = max(dp[i][0][j],dp[i-1][1][j+1]+1);
dp[i][1][j] = max(dp[i][1][j],dp[i-1][1][j]);
if(j!=w)
dp[i][1][j] = max(dp[i][1][j],dp[i-1][0][j+1]);
}
if(num[i]==2){
dp[i][1][j] = max(dp[i][1][j],dp[i-1][1][j]+1);
if(j!=w)
dp[i][1][j] = max(dp[i][1][j],dp[i-1][0][j+1]+1);
dp[i][0][j] = max(dp[i][0][j],dp[i-1][0][j]);
if(j!=w)
dp[i][0][j] = max(dp[i][0][j],dp[i-1][1][j+1]);
}
比较弱,一定有更优的解法,我只会三维的。。。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int num[1005];
int dp[1005][2][35];
int main()
{
int t,w;
scanf("%d%d",&t,&w);
memset(dp,0,sizeof(dp));
for(int i=1;i<=t;i++) scanf("%d",&num[i]);
if(num[1]==1) dp[1][0][w] = 1;
for(int i=1;i<=t;i++)
{
for(int j=w;j>=0;j--)
{
if(num[i]==1){
dp[i][0][j] = max(dp[i][0][j],dp[i-1][0][j]+1);
if(j!=w)
dp[i][0][j] = max(dp[i][0][j],dp[i-1][1][j+1]+1);
dp[i][1][j] = max(dp[i][1][j],dp[i-1][1][j]);
if(j!=w)
dp[i][1][j] = max(dp[i][1][j],dp[i-1][0][j+1]);
}
if(num[i]==2){
dp[i][1][j] = max(dp[i][1][j],dp[i-1][1][j]+1);
if(j!=w)
dp[i][1][j] = max(dp[i][1][j],dp[i-1][0][j+1]+1);
dp[i][0][j] = max(dp[i][0][j],dp[i-1][0][j]);
if(j!=w)
dp[i][0][j] = max(dp[i][0][j],dp[i-1][1][j+1]);
}
}
}
int ma = 0;
for(int i=0;i<=w;i++)
{
ma = max(ma,dp[t][0][i]);
ma = max(ma,dp[t][1][i]);
}
printf("%d\n",ma);
return 0;
}