hdu 3363 Ice-sugar Gourd(转换+尺取)

Ice-sugar Gourd

Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1754    Accepted Submission(s): 579

 

Problem Description

Ice-sugar gourd, “bing tang hu lu”, is a popular snack in Beijing of China. It is made of some fruits threaded by a stick. The complicated feeling will be like a both sour and sweet ice when you taste it. You are making your mouth water, aren’t you?

I have made a huge ice-sugar gourd by two kinds of fruit, hawthorn and tangerine, in no particular order. Since I want to share it with two of my friends, Felicia and his girl friend, I need to get an equal cut of the hawthorns and tangerines. How many times will I have to cut the stick so that each of my friends gets half the hawthorns and half the tangerines? Please notice that you can only cut the stick between two adjacent fruits, that you cannot cut a fruit in half as this fruit would be no good to eat.

Input

The input consists of multiply test cases. The first line of each test case contains an integer, n(1 <= n <= 100000), indicating the number of the fruits on the stick. The next line consists of a string with length n, which contains only ‘H’ (means hawthorn) and ‘T’ (means tangerine).
The last test case is followed by a single line containing one zero.

Output

Output the minimum number of times that you need to cut the stick or “-1” if you cannot get an equal cut. If there is a solution, please output that cuts on the next line, separated by one space. If you cut the stick after the i-th (indexed from 1) fruit, then you should output number i to indicate this cut. If there are more than one solution, please take the minimum number of the leftist cut. If there is still a tie, then take the second, and so on.

Sample Input

 

4 HHTT 4 HTHT 4 HHHT 0

Sample Output

 

2 1 3 1 2 -1

 

Source

“光庭杯”第五届华中北区程序设计邀请赛 暨 WHU第八届程序设计竞赛

题意:一串冰糖葫芦,由H和T组成,你的任务是将H和T分别均分,求最少切的刀数以及切的位置

分析:

特殊情况下两边均分可以中间一刀切好,如果不能一刀均分的话,最多是两刀,而且两个位置相隔一定是n/2。最少一刀好理解,但为什么最多两刀?。

证明:

我们可以把它首位相连成圆,一线将圆分两半(也就两刀)。

整圆设为s,一个半圆设为s1,另一个半圆设为s2。

假设 s中有x个H,y个T,总和为x+y。那么s1的H和T的总和应该为(x+y)/2。

假设 s1有x1个H,y1个T,若x1==x/2,又因为x1+y1==(x+y)/2.所以有y1==y/2。

换句话将就是,只要有一个半圆的H的个数等于整个圆H的个数一半,那么必然这个半圆T的个数也等于整个圆T的一半,那么这个半圆就是我们想要的区间,它的端点就是我们要找的两位置。那么随着移动x1一定会等于x/2吗?它要一定。想要的区间(半圆)就一定存在。下面就是证明x1一定有机会等于x/2。

假设s有x个H,s1有x1个H,s2有x2个H。若x1<x/2,那么一定有x2>x/2。由于线的旋转那么s1一定会移动到s2,所以x1就会等于原来的x2,那么x1随着移动从小于x/2到大于x/2必然经过x/2。所以x1一定有机会等于x/2。

综上所诉,要将H和T均分最多两刀,因为那个半圆区间一定能找到。

后面只需要交个尺取法求(L,L+n/2-1)中的H个数等于整个区间H个数的一半,第一次找到的区间的两端就是答案。

#include <stdio.h>
#include <string>
#include <iostream>
using namespace std;
int main()
{
    int n;
    string str;
    while(cin>>n&&n)
    {
        cin>>str;
        str+=str;
        int h=0,t=0,x=0,y=0;
        for (int i=0; i<n; i++){
            if(i<n/2){
                if(str[i]=='H') h++;
                else t++;
            }
            if(str[i]=='H') x++;
            else y++;
        }
        if(x%2==0&&y%2==0){
            if(h==x/2){
                 printf("1\n%d\n",n/2);
            continue;
            }
        }else{
            printf("-1\n");
            continue;
        }
        int f=0,i=0,j=n/2-1;
        for (int k=1;k<n;k++){
            if(str[i+k-1]=='H') h--;
            else t--;
            if(str[j+k]=='H') h++;
            else t++;
            if(h==x/2){
                f=1;
                printf("2\n%d %d\n",i+k,j+k+1);
                break;
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zero_zp/article/details/81290023