01翻转

牛牛正在挑战一款名为01翻转的游戏。游戏初始有A个0,B个1,牛牛的目标就是把所有的值都变为1,每次操作牛牛可以任意选择恰好K个数字,并将这K个数字的值进行翻转(0变为1,1变为0)。牛牛如果使用最少的操作次数完成这个游戏就可以获得奖品,牛牛想知道最少的操作次数是多少?
例如:A = 4 B = 0 K = 3 
0000 -> 1110 -> 1001 -> 0100 -> 1111 

需要的最少操作次数为4


这个题的关键是理解A=10000,B=10000,K=548时,不需要贪心到134,而是在A=134+K的时候就可以进行两次就可以了。


#include <iostream>
#include <queue>
using namespace std;
  
struct node{
    int x,y,p;
    node(int a,int b,int c):x(a),y(b),p(c){};
};
  
queue<node> fk;
int ft[100005]={0};
int k;
int BFS(){
    int a,b;
    while(!fk.empty()){
        node fn=fk.front();
        fk.pop();
        while(fn.x>=k){
            fn.p+=fn.x/k;
            fn.x=fn.x%k;
        }
        if(fn.x==0){
            return fn.p;
        }
        if((k+fn.x)%2==0 && fn.p>0 && fn.y>=2*k-(fn.x+k)/2)
            return fn.p+1;
        for(int i=1;i<=fn.x;i++){
            if((fn.y+i)>=k){
                a=fn.x+k-i-i;
                b=fn.y-k+i+i;
                if(a==0)
                    return fn.p+1;
                if(ft[a]==0){
                    ft[a]=fn.p+1;
                    node fs(a,b,fn.p+1);
                    fk.push(fs);
                }
            }
        }
    }
    return -1;
}
  
int main(){
    int a,b,minp;
    scanf("%d%d%d",&a,&b,&k);
    if(a==0){
        printf("0\n");
        return 0;
    }
    int sum=a+b;
    int ans=0;
    while(a>=k){
        ans+=a/k;
        a=a%k;
    }
    if(a==0){
        printf("%d\n",ans);
        return 0;
    }
    node tmp(a,sum-a,ans);
    fk.push(tmp);
    ft[a]=ans;
    minp=BFS();
    printf("%d\n",minp);
    return 0;
}

下面是大神的纯数学做法,是考虑ABK的奇偶情况。


#include<iostream>
#include<cmath>
using namespace std;
 
int function(int A, int B, int K){
    int remainder = A % K;
    int count = A / K;
    B += A - remainder;
    if (A == 0 || remainder == 0)
        ;
    else if ((remainder + B <= K) || (remainder % 2 == 1 && K % 2 == 0))
        count = -1;
    else if ((K + remainder) % 2 == 0 && count > 0 && B >= 2 * K - (remainder + K) / 2)
        count++;
    else if (remainder % 2 == 0)
        count += 2 * ceil(remainder / double(2 * (B - K + remainder)));
    else
        count += 2 * ceil((K - remainder) / double(2 * (B - K + remainder))) + 1;
 
    return count;
}
 
int main(){
    int A, B, K;
    cin >> A >> B >> K;
    cout << function(A, B, K);
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值