题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3363
题意:一串冰糖葫芦上串有两种水果,现要将这串冰糖葫芦上的两种水果都均分给两个人,求一共要在这串冰糖葫芦上切几刀。
分析:比赛刚开始写了一道水题后就写的这道题,按照自己的理解从头到尾扫一遍判断需要切的各种情况结果交上错了,我知道是自己思路有问题,于是便先放下了这道题,去写一道dfs的题目。过了好久好久之后,大约还剩一个小时结束比赛又回来想的这道题,但最终还是没A出来,听了同伴的分析后才知道自己傻逼了,我愣是要在从头到尾扫时一遇到该切的地方就切,事实上,如果自己多写几组例子来推推看得话就会知道,如果可以均分成两份的话最多切两刀。我一开始不信,自己写了好多组例子又试了试,结果真的最多只需要切两刀。当我在嘟囔为啥我没发现呢,原来这道题这么简单时,旁边某学长幽幽的说了句你那才试了几组例子,你看我们错了多少遍试了多少例子,看着他草稿纸上满满的测试样例,顿时觉得好羞愧。
思路:输入1~n之后,从[1,n/2]这个区间开始判断,每次保证区间长度不变,整体向后移动一个单位。如果在当前n/2区间长度内满足H T均为总数的一半时,在这区间首尾各切一刀即可。如果是区间[1,n/2],则只需在n/2切一刀即可。
#include<cstdio>
#include<string>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<cstring>
#include<set>
#include<queue>
#include<string>
#include <algorithm>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 100000 + 10;
typedef long long ll;
char ch[maxn];
int a[maxn];
int main()
{
int T;
while(scanf("%d",&T) == 1 && T)
{
getchar();
ll h = 0, t = 0;
for(int i = 1; i <= T; ++i)
{
scanf("%c",&ch[i]);
ch[i] == 'H' ? h++ : t++;//记录H T总数
}
if((h % 2) || (t % 2))
{
printf("-1\n");
continue;
}
h /= 2; t /= 2;
//cout << "h == " << h << " " << "t == " << t << endl;
int tmph = 0, tmpt = 0;
int l = 1,r = T / 2;
for(int i = 1; i <= r; i++)
{
ch[i] == 'H' ? ++tmph : ++tmpt;//先判断区间[1,n/2]是否满足条件
}
//cout << "tmph == " << tmph << " " << "tmpt == " << tmpt << endl;
if(tmph == h && tmpt == t)
{
printf("1\n");
printf("%d\n",r);
continue;
}
int movel,mover;
int flag = 0;
// cout << "l == " << l << " " << "r == " << r << endl;
while(r <= T && !(tmph == h && tmpt == t))//保证区间长度不变,移动区间,直到找到满足条件的为止
{
movel = l; mover = r;
++l; ++r;
ch[movel] == 'H' ? --tmph : --tmpt;
ch[r] == 'T' ? ++tmpt : ++tmph;
if(tmph == h && tmpt == t)
flag = 1;
}
if(flag)
{
printf("2\n");
printf("%d %d\n",l - 1,r);
}
else
printf("-1\n");
}
return 0;
}
//16 HHTHTHHTHTHTHTTT