您的位置:首页 > 其它

Wannafly挑战赛12 C 删除子串 (dp)

2018-03-28 18:04 477 查看
点击打开链接

解析:

Dp[i][j][d]表示前i个字符变化了j次且末尾是0(a)/1(b)的最长的长度
再遍历,这里需要注意因为字符串首字母必须位a,当再遍历结尾为1(b)状态的时候,必须要保证前面有长度!=0。不然的话,首字母就是b,就是非法的了
这里有点类似于之前的一道牛客上的dp题点击打开链接,就是上面这个数据点卡了我一个下午,还是看题解才意识到的

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAXN = 1e5+10;

char s[MAXN];
int val[MAXN];

int dp[MAXN][11][2];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
scanf("%s",s+1);
int len=strlen(s+1);
char bef='a';
int num=0;
int cnt=0;
int flag=1;
int na=0;
int change=0;
int beg=1;
for(int i=1;i<=n;i++)
{
if(s[i]=='a')
{
flag=0;
beg=i;
break;
}
}
if(flag)
{
printf("0\n");
return 0;
}
for(int i=beg;i<=n;i++)
{
if(s[i]=='a')
{
na++;
}
if(s[i]!=bef)
{
val[++cnt]=num;
num=0;
bef=s[i];
change++;
}
num++;
}
val[++cnt]=num;
if(m==0)
{
printf("%d\n",na);
return 0;
}

dp[1][0][0]=val[1];
for(int i=2;i<=cnt;i++)
{
for(int j=0;j<=m;j++)
{
if(i%2==1) //a ->0
{
dp[i][j][0]=max(dp[i-1][j][0],dp[i][j][0]); //删i
dp[i][j][0]=max(dp[i-1][j][0]+val[i],dp[i][j][0]);
if(j/*&&dp[i-1][j-1][1]*/) dp[i][j][0]=max(dp[i][j][0],dp[i-1][j-1][1]+val[i]);

dp[i][j][1]=max(dp[i][j][1],dp[i-1][j][1]); //删i
}
else //b -> 1
{
dp[i][j][1]=max(dp[i][j][1],dp[i-1][j][1]); //删i
if(dp[i-1][j][1])
dp[i][j][1]=max(dp[i-1][j][1]+val[i],dp[i][j][1]);
if(j&&dp[i-1][j-1][0]) dp[i][j][1]=max(dp[i][j][1],dp[i-1][j-1][0]+val[i]);

dp[i][j][0]=max(dp[i-1][j][0],dp[i][j][0]); //删i
}

}
}
int ans=0;
for(int i=m;i>=0;i--)
{
ans=max(ans,dp[cnt][i][0]);
ans=max(ans,dp[cnt][i][1]);
}
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp acm专项训练 ACM