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| +2。

    • (a,b)->(a-1,b+1): ( ( a 1 ) 2 {(a - 1)^2} + ( b + 1 ) 2 {( b + 1)^2} ) - ( a 2 {a^2} + b 2 {b^2} ) = 2(a - b)+2
    • (a,b)->(a+1,b-1): ( ( a + 1 ) 2 {(a + 1)^2} + ( b 1 ) 2 {( b - 1)^2} ) - ( a 2 {a^2} + b 2 {b^2} ) = 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+最大增量。

猜你喜欢

转载自blog.csdn.net/codertcm/article/details/82961890