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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章