AtCoder Grand Contest 037 A

dp

2mathbf 题目意思是给一个字符串然后问你,最多可以分成多少块,要求相邻的2块不能相等。

做法就是dp,因为大小为3的块必定是可以分成大小为1和2的两块的,通过这样子拆分可以知道大小>=3的块都是可以分成大小为1和2的块的合法组合的,且拆分后块的数量更多,所以我们只需要分大小为1和2的块就可以了,定义dp[i][j]为到第i个字符,最后一块大小为j的最大块数.

{ dp[i][1]=max(dp[i1][1],dp[i1][2])+1dp[i][2]=max(dp[i2][1],dp[i2][2] 状态转移方程 egin{cases} dp[i][1]=max(dp[i-1][1],dp[i-1][2])+1& \ dp[i][2]=max(dp[i-2][1],dp[i-2][2]& end{cases}

#include<bits/stdc++.h>
using namespace std;
#define ls rt<<1
#define rs (rt<<1)+1
#define PI acos(-1)
#define eps 1e-8
#define ll long long
#define fuck(x) cout<<#x<<"     "<<x<<endl;
typedef pair<int,int> pii;
const int inf=2e9;
const int maxn=2e5+10;
int d[4][2]={1,0,-1,0,0,1,0,-1};
//int lowbit(int x){return x&-x;}
//void add(int x,int v){while(x<=n)bit[x]+=v,x+=lowbit(x);}
//int sum(int x){int ans=0;while(x>=1) ans+=bit[x],x-=lowbit(x);return ans;}
inline ll read() {
    ll s = 0,w = 1;
    char ch = getchar();
    while(!isdigit(ch)) {
        if(ch == '-') w = -1;
        ch = getchar();
    }
    while(isdigit(ch))
        s = s * 10 + ch - '0',ch = getchar();
    return s * w;
}
inline void write(ll x) {
    if(x < 0)
        putchar('-'), x = -x;
    if(x > 9)
        write(x / 10);
    putchar(x % 10 + '0');
}

char s[maxn];
int dp[maxn][3];

int main(){
    scanf("%s",s+1);
    int n=strlen(s+1);
    dp[1][1]=1;
    dp[1][2]=0;
    dp[2][1]=(s[1]==s[2])?0:2;
    dp[2][2]=1;
    for(int i=3;i<=n;i++)
    {
        if(dp[i-1][1]&&s[i-1]!=s[i])
            dp[i][1]=max(dp[i][1],dp[i-1][1]+1);
        if(dp[i-1][2])
            dp[i][1]=max(dp[i][1],dp[i-1][2]+1);
        if(dp[i-2][1])
            dp[i][2]=max(dp[i][2],dp[i-2][1]+1);
        if(i==3) continue;
        if(dp[i-2][2]&&(s[i-2-1]!=s[i-1]||s[i-2]!=s[i]))
            dp[i][2]=max(dp[i][2],dp[i-2][2]+1);
    }
    write(max(dp[n][1],dp[n][2]));puts("");
    return 0;
}

原文地址:https://www.cnblogs.com/eason9906/p/11754699.html