HDU 5583 Kingdom of Black and White

Description

In the Kingdom of Black and White (KBW), there are two kinds of frogs: black frog and white frog.

Now N frogs are standing in a line, some of them are black, the others are white. The total strength of those frogs are calculated by dividing the line into minimum parts, each part should still be continuous, and can only contain one kind of frog. Then the strength is the sum of the squared length for each part.

However, an old, evil witch comes, and tells the frogs that she will change the color of at most one frog and thus the strength of those frogs might change.

The frogs wonder the maximum possible strength after the witch finishes her job.

Input

First line contains an integer T, which indicates the number of test cases. Every test case only contains a string with length N, including only 0 (representing a black frog) and 1 (representing a white frog).
⋅1≤T≤50⋅
. for 60% data, 1≤N≤1000.
. for 100% data, 1≤N≤105.
⋅ the string only contains 0 and 1.

Output

For every test case, you should output " Case #x: y",where x indicates the case number and counts from 1 and y is the answer.

Sample Input

2
000011
0101

Sample Output

Case #1: 26
Case #2: 10

题意

给你一个只含01的字符串,你可以至多翻转其中的一个字符 (0->1,1->0),使得它的strength值最大。
strength值的计算方法:将连续的并且相同的字符放在一起,构成多个子字符串,由每个子字符串的长度可得一个长为n的序列s,该字符串strength值为s序列每个数的平方和。

思路

  1. 改变相邻两个数a,b,大的数加1,小的数减1。此时增量为2 ∣ a − b ∣ \left|a-b\right| ab+2。

    • (a,b)->(a-1,b+1): ( ( a − 1 ) 2 {(a - 1)^2} (a1)2 + ( b + 1 ) 2 {( b + 1)^2} (b+1)2 ) - ( a 2 {a^2} a2 + b 2 {b^2} b2 ) = 2(a - b)+2
    • (a,b)->(a+1,b-1): ( ( a + 1 ) 2 {(a + 1)^2} (a+1)2 + ( b − 1 ) 2 {( b - 1)^2} (b1)2 ) - ( a 2 {a^2} a2 + b 2 {b^2} b2 ) = 2(b - a)+2
  2. 改变相邻三个数a,1,b,并且中间的数为1。把中间那个数所代表的字符翻转后,前后字符串就相连了,子字符串的长度为a+1+b。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <stack>
#include <cmath>
#include <deque>
#include <vector>
#define N 1000005
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long int LL;

int main()
{
    int T,z=0;
    scanf("%d",&T);
    while(T--)
    {
        vector<LL>v,w;
        deque<char>p;
        char s[N]= {0};
        LL sum1=0,sum2=0;
        scanf(" %s",s);
        for(LL  i=0; s[i]; i++)
        {
            if(p.empty())
            {
                p.push_back(s[i]);
                continue;
            }
            if(p.back()!=s[i])
            {
                v.push_back((LL)p.size());
                w.push_back((LL)p.size());
                p.clear();
                p.push_back(s[i]);
            }
            else
            {
                p.push_back(s[i]);
            }
        }
        if(p.size()!=0)
        {
            v.push_back((LL)p.size());
            w.push_back((LL)p.size());
        }
        LL pos=0,maxs=0;
        for(LL i=1; i<(LL)v.size(); i++)
        {
            if( (LL)(2*abs(v[i-1]-v[i])+2) > maxs)
            {
                pos=i;
                maxs=(LL)(2*abs(v[i-1]-v[i])+2);
            }
        }
        if(pos!=0)
        {
            if(v[pos]>v[pos-1])
            {
                v[pos]++;
                v[pos-1]--;
            }
            else
            {
                v[pos]--;
                v[pos-1]++;
            }
        }
        for(LL  i=0; i<(LL)v.size(); i++)
        {
            sum1+=v[i]*v[i];
        }
        pos=0;
        maxs=0;
        for(LL  i=1; i<(LL)w.size()-1; i++)
        {
            if(w[i]==1)
            {
                if( (2*(w[i-1]+w[i+1])+2*w[i-1]*w[i+1]) > maxs )
                {
                    pos=i;
                    maxs=(2*(w[i-1]+w[i+1])+2*w[i-1]*w[i+1]);
                }
            }
        }
        if(pos!=0)
        {
            for(LL  i=0; i<(LL)w.size(); i++)
            {
                if(i==pos-1)
                {
                    sum2+=(w[i]+w[i+1]+w[i+2])*(w[i]+w[i+1]+w[i+2]);
                    i+=2;
                }
                else
                    sum2+=w[i]*w[i];
            }
        }
        printf("Case #%d: %lld\n",++z,(long long)max(sum1,sum2));
    }
    return 0;
}

看其他博主,还有一种类似dp的写法:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <stack>
#include <cmath>
#include <deque>
#include <vector>
#define N 1000005
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long int LL;

int main()
{
    int T,z=0;
    scanf("%d",&T);
    while(T--)
    {
        vector<LL>v,w;
        deque<char>p;
        char s[N]= {0};
        LL sum=0,ans=0;
        scanf(" %s",s);
        for(LL  i=0; s[i]; i++)
        {
            if(p.empty())
            {
                p.push_back(s[i]);
                continue;
            }
            if(p.back()!=s[i])
            {
                v.push_back((LL)p.size());
                p.clear();
                p.push_back(s[i]);
            }
            else
            {
                p.push_back(s[i]);
            }
        }
        if(p.size()!=0)
        {
            v.push_back((LL)p.size());
        }

        for(LL i=0;i<v.size();i++)
            sum+=v[i]*v[i];
        ans=sum;
        for(int i=1;i<v.size();i++)
        {
            if(v[i]==1 && i!=v.size()-1)
            {
                ans=max(ans,sum+2*(v[i-1]+v[i+1])+2*v[i-1]*v[i+1]);
            }
            else
            {
                ans=max(ans,sum+2*abs(v[i]-v[i-1])+2);
            }
        }
        printf("Case #%d: %I64d\n",++z,ans);
    }
    return 0;
}

总结

求连续三个数的时候,把三个数的和的平方当做判断是否修改这三个值得依据,其实应该是把改变这三个值之后能带来的增量当做判断条件。
dp的写法挺好的,找到最优解就行了,就是原数组的sum+最大增量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值