zzulioj-1961-取硬币【思维】【贪心】

题目链接:点击打开链接

1961: 取硬币

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 46   Solved: 6

Submit Status Web Board

Description

n个硬币排成一排,你可以取走其中连续的一段硬币,但必须要求这段硬币中正面朝上的个数等于反面朝上的个数,那么你最多可以取走多少枚硬币?

Input

多组实例测试,每组输入一个01字符串(长度小于1000000),其中0表示反面朝上,1表示正面朝上

Output

对于每组数据,输出能取走的最多硬币数量

Sample Input

10110

Sample Output

Case #1: 4

思路:

令temp为当前1的个数与0的个数的差(可以为负,例如1的个数为5,0的个数为8,那么差就为-3),
那么只需要从左到右遍历一遍字符串,不停更新temp值即可,只要这个temp值之前出现过,就说明中间这一段0和1的个数一定相等
比如str[] = "110101111":
我们设i=xi表示当前遍历到第xi个字符
xi=1时,a=1,b=0,temp=1
xi=2时, a=2,b=0,temp=2
xi=3时, a=2,b=1,temp=1(和x1=1时相等,那么找到一个01相等串,长度为2)
xi=4时, a=3,b=1,temp=2(和x1=2时相等,那么又找到一个01相等串,长度也为2)
xi=5时, a=3,b=2,temp=1(和x1=1时相等,找到一个01相等串,长度为4!更优)

.......
xi=7, a=5,b=2,temp=3
xi=8, a=6,b=2,temp=4  ……
综上,答案为4!
PS:用一个数组p[2000005]来存temp的值,因为temp可以为负,所以我们将temp总体+1000000,,p[temp]=5表示temp值最早出现在下标为5的地方

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXN=1e6+10;
char str[MAXN];
int pos[2*MAXN]; // pos[i]=j :记录第一次出现 0 与 1 差值为 i的位置为 j 
int main()
{
	int text=0;
	while(~scanf("%s",str+1))
	{
//		printf("%d--\n",strlen(str+1));
		memset(pos,0,sizeof(pos));
		int cnt0=0,cnt1=0,ans=0;
		for(int i=1;str[i];i++)
		{
			if(str[i]=='0')
				cnt0++;
			else
				cnt1++;
			int k=cnt0-cnt1+MAXN;
			if(pos[k]||cnt0==cnt1)
			{
				ans=max(ans,i-pos[k]);
			}
			else
				pos[k]=i;
		}
		printf("Case #%d: %d\n",++text,ans);
	}
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值