EOJ 1854 - Broken Necklace

题意:红蓝白三色珠子组成的项链从中间某处断开,从两端各取某种相同颜色的珠子,其中白色可当作红色或蓝色,要取到最多的珠子应该从哪里断开,可以得多少?

EOJ 1854 - Broken Necklace

例子如下:
w w w b b r w r b r b r r b r b r w r w w r b w r w r r|b
* * * * *|                                   |* * * * *|*
这种取法可以拿到5个红珠和6个蓝珠,为最多。
由于题给数据不大(<350个),因此可以直接遍历所有的拆项链可能,并统计两端最多能收集的珠子数(需要注意两端有可能相接的特殊情况)。

有没有可能优化这个暴力算法呢?既然想要收集最多的珠子,自然如果能同时收集两种颜色的最好,所以会希望把分隔点尽可能放在颜色的交界处。


#include <iostream>

using namespace std;

int main()
{
    char beads[800];
    int i,n,st=0,z,f,max=0;
    cin>>n;
    z=0,f=0;
    cin.ignore();
    for(i=0; i<n; i++) {
        cin>>beads[i];
        beads[n+i]=beads[i];//把数组重复两遍,即有首尾循环的效果
    }
    char pre;
    int cnt;
    int loop=0;
    for(st=0; st<n; st++) {
        if(beads[st+n-1]==beads[st+n]) {
            continue;    //节约时间,排除分开点左右相同不可能最优的情况
        }
        loop=1;//但是还可能有全都相同的情况
        int tag;
        cnt=0;
        pre=beads[st];

        for(i=st; i<st+n; i++) {

            if(beads[i]=='w') {
                cnt++;//白色不影响,计数器+1
            } else if(beads[i]!=pre) {//颜色有变化
                if(pre=='w') {
                    cnt++;
                    pre=beads[i];//有可能出现开头即白色的情况
                } else {
                    z=cnt;
                    tag=i;//记录已访问的位置,反向时至多到此停止
                    break;//颜色不同,打断
                }
            } else {
                cnt++;//同颜色,计数器+1
            }
        }
        if(z==0) {
            z=cnt;
        }

        cnt=0;
        pre=beads[st+n-1];

        for(i=st+n-1; i>=st; i--) {
            if(i==tag) {
                f=(n-z);
                break;
            }
            if(beads[i]=='w') {
                cnt++;
            } else if(beads[i]!=pre) {
                if(pre=='w') {
                    cnt++;
                    pre=beads[i];
                } else {
                    f=cnt;
                    break;
                }
            } else {
                cnt++;
            }
        }
        if(z+f>max) {
            max=z+f;
        }
    }

    if(loop==0) {
        max=n;    //如果loop=0说明全相同,可取n个
    }

    cout<<max<<endl;
    return 0;
}





你可能感兴趣的:(贪心,暴力求解)