2020 百度之星 复赛 1002 Binary Addition

2020 百度之星 复赛 1002 Binary Addition

题目

http://acm.hdu.edu.cn/showproblem.php?pid=6839

题意

给你一串无限长的01串S、T,其中第n+1位及以后都是0。现你有两种操作作用于S串:
1、将某一位0变成1,1变成0.
2、将其视为一个数,对它+1。其中最低位在最左边
求最小的操作次数,使得S串变成T串。

题解

可以知道+1的操作最多使用一次,那么什么时候进行+1操作可以得到最小解呢?
可以for循环每一位都进行+1操作,最后维护他的最小值。
我们考虑每一位的时候都是考虑 前i+1位的变化。

11111
00000

考虑第1位+1的情况,是变成这样的,操作数是6

把前i位0变成1
11111 
执行+1操作,那么理想情况前i位都会变成0,第i+1位会变成1
00111
因为s的第i+1位本来就是1,所以操作数+1
01111
因为t的第i+1位是0,不符合s的理想情况,所以操作数+1,把s的第i+1变回0
00111
最后再加上从第i+2位到第n位,s和t一共有多少不同的数就可以了
00011
00001
00000
通过这个例子我们可以发现,其实当s[i+1]==1&&t[i+1]==0的时候步骤都是多余的
所以我们再实际操作的时候可以跳过s[i+1]==1&&t[i+1]==0的时候.

用num0[i]记录S的第i位之前有多少个0,在进行+1操作之前,要把S所有的0都变成1。
用num1[i]记录T的第i位之前有多少个1,在进行+1操作之后,要把前i位的都变成1。
因为+1操作之后会进一位,所以我们还要判断下一位
如果s[i+1]==1 ,那进位操作会把它变成0,所以我们要把它变回来,操作数就+1,
如果t[i+1]==0,那么和s[i+1]不相等,操作数也要+1。
最后再加上从第i+2位到第n位,s和t一共有多少不同的数就可以了。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
#define PI acos(-1)
const int maxn = 1e5+5;
const ll mod = 998244353;
const double eps = 1e-6L;
char s[maxn],t[maxn];
int num0[maxn],num1[maxn],cnt[maxn];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        scanf("%s",&s);
        scanf("%s",&t);
        t[n]= '0';
        for(int i=0;i<n;i++)
        {
        	if(i==0)
        	{
        		num0[i] = -s[i]+'1';
        		num1[i] = t[i]-'0';
			}
        	else
        	{
        		num0[i] = num0[i-1]-s[i]+'1';
        		num1[i] = num1[i-1]+t[i]-'0';
			}
		}
		cnt[n]=0;cnt[n+1]=0;
		for(int i=n-1;i>=0;i--)
		{
			cnt[i] = cnt[i+1]+(s[i]==t[i]?0:1);
		}
		int ans = cnt[0];//全部都执行更改操作 
		for(int i=0;i<n;i++)//前i位的0都变成1,然后进行+1操作 
		{
			if(s[i+1]=='1'&&t[i + 1] == '0')	continue;
			int sum = 1+num0[i]+(s[i+1]=='1')+num1[i]+(t[i + 1] == '0') + cnt[i + 2];
//			printf("sum = %d t[i+1] = %d\n",sum,t[i + 1] == '0');
			ans = min(ans,sum);
		}
		printf("%d\n",ans);
    }
    return 0;
}
/*
5
5
11111
00000
5
10100
01010
5
00000
00001
7
1111110
0100001
7
0011110
0100001
*/
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值