首页 > 试题广场 >

01翻转

[编程题]01翻转
  • 热度指数:1902 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
牛牛正在挑战一款名为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(0 ≤ A ≤ 100,000),B(0 ≤ B ≤ 100,000),K(1 ≤ K ≤100,000).以空格分隔


输出描述:
输出一个整数,表示最少需要的操作次数。如果不能完成,则输出-1
示例1

输入

4 0 3

输出

4
本人比较喜欢数学,就从数学的角度来解这道题吧
设 n = A+B
设 位置值序列集合 E = {e1, e2, e3,... en}, ei ∈ {0, 1},其中ei表示第i个位置上的值 (1 ≤ i ≤ n)
假设初始时,前面A个位置为0,后面B个位置为1
设 Ti 为 第i个位置上翻转的次数
因为一次翻转必翻转K个位置,假设进行了X次翻转(未知数),则有以下等式
① XK = ∑Ti (1 ≤ i ≤ n)
因为同一个位置翻转2次得到是原来的值,所以为了使所有位置均为1, Ti 必满足以下条件:
② Ti = 1 + 2Si (ei 初始为0)
③ Ti = 2Si(ei 初始为1)
其中Si 表示第i个位置进行了 Si次2次翻转
结合①、②、③可得:
④ XK = A + 2 ∑Si (1 ≤ i ≤ n)
XK - A 必为偶数
我对此的理解为,总的来看:在某些位置上进行了2次翻转,和A个位置的1次翻转,就全部为1了。
对 ∑Si 观察可得:
对于初始为1的位置,2次翻转次数不能超过X/2
对于初始为0的位置,2次翻转次数不能超过(X-1)/2 ,因为最后一次翻转不能属于“2次翻转”中的一次翻转
我们假设所有位置的2次翻转次数都达到最大,则有不等式:
⑥ (XK - A)/2 = ∑Si (1 ≤ i ≤ n)≤ A ((X-1)/2) + B(X/2)
满足⑤、⑥条件X即可满足题意
我们可以相信,X不能大于 A的最大值+B的最大值 = 200000
#include <iostream>
using namespace std;
int main() {
    int K,A,B, MAX = 200000;
    while(cin>>A>>B>>K) {
        int N;
        for (N = 0; N < MAX; N++) {
            if ((N*K - A) < 0 || ((N*K - A) & 0x1) != 0) 
                continue;
            if ((N*K - A)/2 <= A*((N-1)/2) + B*(N/2) || A == 0) 
                break;
        }
    	if (N < MAX) 
            cout<<N<<endl;
        else 
            cout<<-1<<endl;
    }
    return 0;
}

编辑于 2017-03-19 11:43:09 回复(17)
#include<iostream>
#include<cmath>
using namespace std;

int function(int A, int B, int K){
	int remainder = A % K;//直接翻转后的剩余待翻转个数
	int count = A / K;//直接翻转
	int S = A + B;//总个数
	if (A == 0 || remainder == 0)
		;
	else if ((S <= K) || (remainder % 2 == 1 && K % 2 == 0))
		count = -1;//无法翻成功的输出-1
	else if ((K + remainder) % 2 == 0 && count > 0 && B + K * count >= 2 * K - (remainder + K) / 2)
		count++;//一种特殊情况,还剩下K+remainder个0时直接翻两次即可完成
	else if (remainder % 2 == 0)
		count += 2 * ceil(remainder / double(2 * (S - K)));
       //每翻两次最多能把remainder中的2*(S-K)个0翻成1,注意这里指的是最多,当翻最后2次或者S-K>remainder/2时,只需翻两次,所以这里用到了ceil()
	else
		count += 2 * ceil((K - remainder) / double(2 * (S - K))) + 1;
       //当remainder是奇数时,相当于先把所有1中的K-remainder个翻成0,这样加上remainder一共K个0,只需额外再翻一次即可,K-remainder是奇数时,永远不能翻成功,是偶数时,翻转方法同上面
	return count;
}

int main(){
	int A, B, K;
	cin >> A >> B >> K;
	cout << function(A, B, K);
	return 0;
}
//没有循环,只用到了条件语句,时间复杂度O(1),空间复杂度O(1)

编辑于 2017-03-25 20:25:21 回复(14)
import sys
def main(A, B, K):
    if A == 0: return 0
    if K == 0: return -1
    if A % K == 0: return A / K
    if A & 1 > K & 1 or K >= A + B: return -1
    ret = A // K + 1
    while 1:
        if (ret * K - A) & 1 == 0 and ret * K <= ret * (A + B) - (A, B)[ret & 1]:
            return ret
        ret += 1
print main(*map(int, sys.stdin.readline().split()))

循环也可以改成O(1)的算法,可读性就差了。
发表于 2017-03-28 05:17:25 回复(0)
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
/*
 * 问题:一行数字,初始有a个0和b个1,现在目标是把所有的值都变为1,每次可以任意选择恰好k个数字,并将这个k个数字
 * 的值进行翻转(0变成1,1变成0)。请问达到目标最少需要几次操作。
 */
/*
 * 有初始状态和结束状态,求最少操作次数。显然这是一个宽度优先遍历(BFS)
 * 初始状态:a个0,b个1
 * 结束状态:0个0,(a+b)个1
 * 边(规则):每次可以翻转k个数
 */
public class FanZhuan {
	public static void main(String[] args) {
		Scanner scanner=new Scanner(System.in);
		int a=scanner.nextInt();
		int b=scanner.nextInt();
		int k=scanner.nextInt();
		scanner.close();
		
		int count=BFS(a, b, k);
		System.out.println(count);
	}
	public static int BFS(int a,int b,int k){
		if(a==0 && b==0){
			return 0;
		}
		if(k>a+b){
			return -1;
		}
		
		Node node=new Node(a, b, 0);//初始状态
		Queue<Node> queue=new LinkedList<>();//队列
		boolean[] vis=new boolean[a+b+1];//判断是否出现过
		Arrays.fill(vis, false);//全部初始化成false
		queue.add(node);
		vis[a]=true;
		while(!queue.isEmpty()){
			Node temp=queue.poll();
			if(temp.a==0){
				return temp.step;
			}
			//选择k个数字进行反转,假设选择了i个0,i要小于等于a和k的最小值,i至少为1
			//这时1翻转的次数就为k-i
			for(int i=1;i<=Math.min(temp.a, k);i++){
				if(temp.b<k-i){//没有那么多1可供翻转,那就继续,多翻转一个0
					continue;
				}
				int newa=temp.a-i+(k-i);//翻转i个0后,还剩余的0的个数。
				if(newa==0){
					return temp.step+1;
				}
				//判断newa个0的情况有没有出现过
				if(!vis[newa]){
					vis[newa]=true;
					queue.add(new Node(newa, a+b-newa, temp.step+1));
				}
				
			}	
		}
		return -1;
		
	}
}
class Node{
	int a;//表示0的个数
	int b;//表示1的个数
	int step;//表示操作次数
	public Node(int a,int b,int step) {
		this.a=a;
		this.b=b;
		this.step=step;
	}
}


发表于 2017-07-13 12:04:54 回复(1)
import java.util.Scanner;
public class Main{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int A = sc.nextInt();
        int B = sc.nextInt();
        int K = sc.nextInt();
        sc.close();
        int g = A % K;
        if (g == 0) {//能直接整除
            System.out.println(A / K);
            return;
        }
        if (A + B <= K) {//缺少交换空间
            System.out.println("-1");
            return;
        }
        if ((K % 2 == 0) && (g % 2 == 1)) {//剩余0的个数总为奇数,不可能有结果
            System.out.println("-1");
            return;
        }
        //下面分支对交换空间是否充足进行分析
        //交换空间成立条件A + B - g >= K - g / 2(其中最差的情况就是g=2时)
        //说明只要在一次交换中尽可能减小g的值,就能最快的完成全部交换
        if (g == A) {
            int count = 0;
            if (K % 2 == 0) {//如果K为偶数,则当前剩余0的个数一定是偶数
                while (true) {
                    if ((g % 2 == 0) && (A + B - g >= K - g / 2)) {
                        count = count + 2;
                        break;
                    }
                    if (count % 2 == 0) {
                        count++;
                        g = A + B - (K - (A + B - g));
                    }
                    if (count % 2 == 1) {
                        count++;
                        g = K - g;
                    }
                }
            } else {
                while (true) {//如果K为偶数,则当前剩余0的个数是一次奇数一次偶数的交替
                    if ((g % 2 == 0) && (A + B - g >= K - g / 2)) {
                        count = count + 2;
                        break;
                    }
                    if (g % 2 == 0) {
                        count++;
                        g = A + B - (K - (A + B - g));
                    }
                    if (g % 2 == 1) {
                        count++;
                        g = K - g;
                    }
                }
            }
            System.out.println(A / K + count);
            return;
        }
        if (A > 2 * K||B >(K+(g-A)/2)) {
            //举例A=10000 B=10000 K=548时,不需要贪心的交换到A剩余136的时候
            //只需要交换到684的时候,进行两次交换即可全1,而不是贪心到底要多一次
            System.out.println(A / K + 1);
            return;
        }
        if (g < A)
            if (g % 2 == 0) {
                System.out.println(A / K + 2);
                return;
            } else {
                System.out.println(A / K + 3);
                return;
            }
    }
}

发表于 2017-03-12 13:50:28 回复(3)
假设最后剩下的是a个0,此时a<2k,如果a==nk,那次数就直接是a/k了。接下来,假设在a个0中选择n个0进行翻转,则相应的翻转k-n个1,此时有(k-n)+(a-n)=k+a-2n个0,令其等于k可以得到a-2n=0,所以如果a是偶数,那么需要a/k+2次翻转。
如果a是奇数,分两种情况,一是k是奇数,那么选择直接翻转这a个0,奇数-奇数得到偶数,回到上面一种情况,需要a/k+3次翻转。二是k是偶数,那么k+a-2n是偶数+奇数-偶数还是奇数,不可能使得a为偶数,所以此种情况下无解。
——————————
上述情况只适用于1的数量足够的情况,这种方法只能通过80%的用例,还是要使用BFS的方法来通过所有用例。

编辑于 2017-03-10 11:43:35 回复(5)
# coding=utf-8

"""
@author: beyourself
@time: 2018/5/28 9:58
@file: 01flip-flop.py
"""

A, B, K = [int(i) for i in input().split()]
MAX = 200000
for N in range(0, MAX + 2):
    if (N * K - A < 0) or (((N * K - A) & 0x1) != 0):
        continue
    if ((N * K - A) // 2 <= A * ((N - 1) // 2) + B * (N // 2)) or (A == 0):
        break

if N < MAX:
    print(N)
else:
    print('-1')
发表于 2018-05-28 10:10:52 回复(0)

import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

class Step {
	public int a;
	public int b;
	public int step;
	public Step(int a, int b, int step) {
		super();
		this.a = a;
		this.b = b;
		this.step = step;
	}
	
}

public class Main {
	
	private static Scanner in = new Scanner(System.in);
	
	public static void main(String[] args) {
		
		int a = in.nextInt();
		int b = in.nextInt();
		int k = in.nextInt();
		int ans = BFS(a,b,k);
		System.out.println(ans);	
		
	}
	
	public static int BFS(int a, int b, int k) {
		int n = a+b;
		boolean[] vis = new boolean[n+1];
		Arrays.fill(vis, false);
		Queue<Step> q = new LinkedList<>();
		Step start = new Step(a,b,0);
		q.offer(start);
		vis[a] = true;
		
		while(!q.isEmpty()) {
			Step s = q.poll();
			if(s.a == 0) {
				return s.step;
			}
			for(int i = 1; i <= Math.min(s.a, k); i++) {
				if(s.b < k-i) {
					continue;
				}
				int next = s.a-i+(k-i);
				if(next == 0) {
					return s.step+1;
				}
				if(!vis[next]) {
					vis[next] = true;
					q.offer(new Step(next, n-next, s.step+1));
				}
			}
		}
		return -1;
	}
	
}

编辑于 2017-03-19 17:31:59 回复(1)
//用的队列的方法,要注意一个特殊情况(不一定非要贪心到最小),如果出现80%通过一般就是没有考虑这个。
#include <iostream>
#include <queue>
using namespace std;
  
struct node{
    intx,y,p;
    node(inta,intb,intc):x(a),y(b),p(c){};
};
  
queue<node> fk;
intft[100005]={0};
intk;
intBFS(){
    inta,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){
            returnfn.p;
        }
        if((k+fn.x)%2==0&& fn.p>0&& fn.y>=2*k-(fn.x+k)/2)//这就是特殊情况的判定
            returnfn.p+1;
        for(inti=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)
                    returnfn.p+1;
                if(ft[a]==0){
                    ft[a]=fn.p+1;
                    node fs(a,b,fn.p+1);
                    fk.push(fs);
                }
            }
        }
    }
    return-1;
}
  
intmain(){
    inta,b,minp;
    scanf("%d%d%d",&a,&b,&k);
    if(a==0){
        printf("0\n");
        return0;
    }
    intsum=a+b;
    intans=0;
    while(a>=k){
        ans+=a/k;
        a=a%k;
    }
    if(a==0){
        printf("%d\n",ans);
        return0;
    }
    node tmp(a,sum-a,ans);
    fk.push(tmp);
    ft[a]=ans;
    minp=BFS();
    printf("%d\n",minp);
    return0;
}
发表于 2017-03-18 22:34:02 回复(1)

1. 很像网易游戏雷火那道推箱子题目,宽度优先

2. 0 和 1 的个数决定当前状态,更确切说0的个数旧决定了当前状态。 如果下一步翻转i个0 ,则必然要翻转 K-m 个1,遍历0的合法的翻转个数,从而推出下一个所有可能状态。 每个状态记录到达此状态的转移步数,用mm记录, 从上一个状态到下一个状态,下一个状态步数即上一个状态步数+1第一次到达0个0的状态的步数就是最短步数

3. 注意边界条件,没有0的时候不需要翻转,输出0.

4.不要试图用标准库的unordered_map,会超时,用数组存储状态。


#include
#include
#include
#include
using std::vector;
using std::cout;
using std::cin;
using std::string;
using std::queue;
int main()
{
    int A ;
    int B ;
    int K ;
    cin>>B>>A>>K ;
// if no zeros , no need to change, number of steps = 0
    if(B==0){cout<<0;return 0;}
    int mm[A+B+1];
    for(int i =0 ; i< A+B+1; i++)mm[i]= 0;

    mm[B] = 1;
    queue> que ;
    que.push({A,B});
    while(!que.empty())
    {
          vector tt = que.front();
          que.pop();
          int ones = tt[0];
          int zeros= tt[1];  
          int maxE = K-ones > 0 ? K-ones:0;
          for(int i = zeros>K?K:zeros; i>=maxE ; i--)
           if(mm[zeros - i + (K-i)]==0)
          { 
               if(zeros - i + (K-i) ==0){
               cout <<mm[zeros];
               return 0;
           }
              mm[zeros -i + (K-i)] = mm[zeros]+1;
             que.push({ones+i-(K-i) , zeros - i+(K-i)});   
          }          
    }
  cout <<-1;
  return 0;
}

编辑于 2017-03-18 15:55:35 回复(0)

import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

/*
 * 参考大神:https://www.nowcoder.com/questionTerminal/9c4c9d10e3db4448b906c6e6cea22b7f @OceanFan
 * 有部分人使用数学推断得到结果但是比较难想,使用bfs还好理解一点
 * 有起始状态和结束状态,计算其中的变化信息考虑使用bfs
 * */
public class Reverse01 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            int a = scanner.nextInt();
            int b = scanner.nextInt();
            int k = scanner.nextInt();
            System.out.println(reverse01(a, b, k));
        }
    }

    private static int reverse01(int a, int b, int k) {
//        已经完成
        if (a == 0 && b == 0) {
            return 0;
        }
//        不可能反转成功
        if (a + b < k) {
            return -1;
        }

        boolean[] visited = new boolean[a + b + 1];
        Queue<Node> queue = new LinkedList<>();
        queue.add(new Node(a, b, 0));
        visited[a] = true;
        while (!queue.isEmpty()) {
            Node tmp = queue.poll();
            if (tmp.a == 0) {
                return tmp.times;
            }
//            对于1~min(tmp.a,k)个0进行反转
            for (int i = 1; i <= Math.min(tmp.a, k); i++) {
//                1不够反转,继续操作
                if (k - i > tmp.b) {
                    continue;
                }
                int newa = tmp.a - i + (k - i);
                if (newa == 0) {
                    return tmp.times + 1;
                }
                if (!visited[newa]) {
                    visited[newa] = true;
                    queue.add(new Node(newa, tmp.a + tmp.b - newa, tmp.times + 1));
                }
            }
        }
        return -1;
    }

    private static class Node {
        int a, b, times;

        public Node(int a, int b, int times) {
            this.a = a;
            this.b = b;
            this.times = times;
        }
    }
}
发表于 2018-04-15 19:01:35 回复(0)
。。。贴的代码总是乱。。。。。。
编辑于 2017-09-24 08:49:43 回复(0)


import java.util.Arrays;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner sc = new Scanner(System.in);
        int A = sc.nextInt();
        int B = sc.nextInt();
        int K = sc.nextInt();
        test(A, B, K);
    }

    public static void test(int A, int B, int K) {
        int length = A + B + 1;
        int[] arrived = new int[length];
        Arrays.fill(arrived, -1);
        int step = 0;
        arrived[A] = step;
        
        while (arrived[0] == -1) {
            
            arrived = move(arrived, K, step);
            step++;
        }

        System.out.println((arrived[0] == -2 ? -1 : arrived[0]));

    }

    public static int[] move(int[] arrived, int K, int step) {
        int length = arrived.length;
        int[] newArrived = arrived.clone();
        boolean flag = false;
        for (int i = 0; i < length; i++) {
            if (arrived[i] == step) {
                int minZeroTurns = -1 * (Math.min(0, length - 1 - i - K));
                int maxZeroTurns = Math.min(K, i);
                for (int j = minZeroTurns; j <= maxZeroTurns; j++) {
                    int index = i + K - 2 * j;
                    if (0 <= index && index <= length - 1) {
                        if (newArrived[index] == -1) {
                            newArrived[index] = step + 1;
                            flag = true;
                        }
                    }
                }
            }
        }
        if (!flag) {
            newArrived[0] -= 1;
        }
        return newArrived;
    }
}
 
发表于 2017-09-16 21:16:40 回复(0)
//使用深搜,通过只有70%。。。。。。 import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;

/**
 * Created by Administrator on 2017/8/21.
 * 模拟1--01翻转
 */
public class Main {
    static int count;
    static int min;
    public static void main(String []args){
        Scanner in = new Scanner(System.in);
        while (in.hasNext()){
            int a = in.nextInt();
            int b = in.nextInt();
            int k = in.nextInt();
            if (a==0){
                System.out.println(0);
                continue;
            }

            count = 0;
            HashMap<Integer,Integer> hashMap = new HashMap<Integer, Integer>(a+b);
            hashMap.put(a,b);
            min = Integer.MAX_VALUE;
            solve(a,b,k,hashMap);
            if(min!=Integer.MAX_VALUE)
                System.out.println(min);
            else
                System.out.println(-1);
        }

    }

    private static boolean solve(int a, int b, int k, HashMap<Integer, Integer> hashMap) {
        if (a%k==0){
            count++;
            min = Math.min(min,count);
            return true;
        }

        for (int i = 0; i <=k && i<=a; i++) {
            if (b<k-i){
                continue;
            }
            if (!hashMap.containsKey(a-i+k-i)){
                hashMap.put(a-i+k-i,b-(k-i)+i);
                count++;
                solve(a-i+k-i,b-(k-i)+i,k,hashMap);
                count--;
                hashMap.remove(a-i+k-i);

            }
        }
        return false;
    }
} 


编辑于 2017-08-21 20:44:26 回复(0)
/*
用个最傻的办法,遍历翻牌子的状态空间,跑的慢,不过也没超时
*/
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
int main(){
	int a, b, k;
	while ((cin >> a >> b >> k)){
        int n = a + b;//最大0的个数
        vector<int> dp(n + 1, 0);//记录到达i个0状态的最少步数,0表示不可达
        queue<int> q;
        //去一些最简单的情况
	if (a == 0) cout << 0 << endl;
	else if (k >= a + b){
		if (k == a) cout << 1 << endl;
		else cout << -1 << endl;
	}
	else{
            dp[a] = 1;//初始状态
            q.push(a);
            while (!q.empty()){
                a = q.front();//当前状态a个0,n-a个1
                q.pop();
                for (int i = min(k, a); i >= 0; --i){//i为翻0的个数
                    if (k - i > n - a) break;//k-i为翻1的个数,不够翻就退出循环
//翻i个0,0的个数-i,就得翻k-i个1,0的个数+k-i,总计0个数的变化=-i+k-i=k-2*i
                    int new_a = a + k - 2 * i;//翻完后0的个数
                    if (dp[new_a] == 0){
                        dp[new_a] = dp[a] + 1;
                        q.push(new_a);
                    }
                }
            }
            cout << dp[0] - 1 << endl;
		}
	}

	return 0;
}

发表于 2017-07-21 11:12:56 回复(0)

using System;
using System.Collections.Generic;
class Program{
    public static void Main(){
        string line;
        while((line=Console.ReadLine())!=null){
            int A=int.Parse(line.Split()[0]);
            int B=int.Parse(line.Split()[1]);
            int K=int.Parse(line.Split()[2]);
            int[] array=new int[A+B+1];
            for(int i=0;i<array.Length;i++){
                array[i]=-1;
            }
            array[A]=0;
             Queue<int> queue = new Queue<int>();
            queue.Enqueue(A);
            while (queue.Count > 0)
            {
                int t = queue.Dequeue();
                for (int i = K % 2; i <= K; i += 2)
                {
                    if (i == 0)
                        continue;
                    if (t + i >= 0 && t + i <= A + B && (A + B - t - i) >= (K - i) / 2 && t >= (K - i) / 2 && array[t + i] == -1)
                    {
                        array[t + i] = array[t] + 1;
                        queue.Enqueue(t + i);
                    }
                    if (t - i >= 0 && t - i <= A + B && t - i >= (K - i) / 2 && (A + B - t) >= (K - i) / 2 && array[t - i] == -1)
                    {
                        array[t - i] = array[t] + 1;
                        if (t - i == 0)
                        {
                            queue.Clear();
                            break;
                        }
                        queue.Enqueue(t - i);
                    }
                }
            }
            Console.WriteLine(array[0]);
        }
    }
}

发表于 2017-05-09 13:34:42 回复(0)
import java.util.*;  class Step { public int a;  public int b;  public int step;  public Step(int a, int b, int step) { this.a = a;  this.b = b;  this.step = step;  }
} public class Main { public static void main(String[] args) {
        Scanner in = new Scanner(System.in);  int a = in.nextInt();  int b = in.nextInt();  int k = in.nextInt();  int ans = BFS(a,b,k);  System.out.print(ans);  } public static int BFS(int a, int b, int k) { int n = a+b;  boolean[] vis = new boolean[n+1];  Arrays.fill(vis, false);  Queue<Step> q = new LinkedList<>();  Step start = new Step(a,b,0);  q.offer(start);  vis[a] = true;  while(!q.isEmpty()) {
            Step s = q.poll();  if(s.a == 0) { return s.step;  } for(int i = 1; i <= Math.min(s.a, k); i++) { if(s.b < k-i) { continue;  } int next = s.a-i+(k-i);  if(next == 0) { return s.step+1;  } if(!vis[next]) {
                    vis[next] = true;  q.offer(new Step(next, n-next, s.step+1));  }
            }
        } return -1;  }
}

发表于 2017-04-14 15:51:19 回复(0)
用深搜的,通过50%,一直报错“请检查是否存在数组越界等非法访问情况”,但是检查了好
几遍也没发现有数组越界的情况,是不是递归导致栈溢出了?
import java.util.*;
public class Main{     
    static int tmin(int zeros, int ones, int k, boolean visited[]){
        if(zeros == 0)  return 0;
        if(zeros == k) return 1;
        if(visited[zeros])  return -1;//陷入无限循环中,无解
        visited[zeros] = true;
        int re_max = Math.min(zeros, k);//最多反转max个0
        int re_min = Math.max(0,k - ones);//最少反转min个0
        //re_min可能与re _max相等
        int min =  -1;//无解
        //i:反转i个0,剩下的用于反转1
        for(int i = re_min; i <= re_max; ++i){
            int nzeros = zeros - i + (k - i);
            int tmp = tmin(nzeros,ones+zeros-nzeros,k,visited);
            if(tmp == -1)	continue;
            else if(min == -1) min = tmp;
            else min = Math.min(min,tmp);
        }
        if(min == -1)   return -1;
        else return min+1;
    }
    public static void main(String[] arg){
        Scanner sc = new Scanner(System.in);
        int zeros = sc.nextInt(), ones = sc.nextInt(), k = sc.nextInt();
        if(k > ones+zeros)  return ;
        if(k == 0 || zeros < 0 || ones < 0)  return ;
        boolean visited[] = new boolean[zeros+ones+1];
        System.out.print(tmin(zeros,ones,k,visited));
        return ;
    }
}

发表于 2017-03-24 21:05:48 回复(0)

include<iostream>

using namespace std;

int main() { int A,B,K; cout>A>>B>>K; int x,y,m,n,t; x=A%K; y=B%K; m=A/K; n=B/K; if(x==0) { t=m; } else { if(x%2==0) { t=m*2+x; } else { t=m-1+x/2+K+1; } } cout<<"需要最少的操作次数是:"<<t<<endl; }

编辑于 2017-03-21 21:33:23 回复(0)
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;

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


public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while(sc.hasNext()){
            Integer a = sc.nextInt();
            Integer b = sc.nextInt();
            Integer n = a+b;
            Integer k = sc.nextInt();

            System.out.println(caozuo3(a,n,k));
        }
    }

/**
BFS遍历
**/
    public static int caozuo3(int a,int n,int k){
        if (a==0){
            return 0;
        }
        Queue<Integer> queue = new LinkedList<Integer>();
        int[] visited = new int[n+1];
        int[] disk = new int[n+1];
        queue.offer(a);
        visited[a] = 1;
        disk[a] = 0;
        while (!queue.isEmpty()){
            int local = queue.remove();
            for (int i=1;i<=k;i++){
                if (i<=local&&k-i<=n-local){
                    int next = local-2*i+k;
                    if (visited[next]==0){
                        if (next==0)return disk[local]+1;
                        queue.offer(next);
                        visited[next] = 1;
                        disk[next] = disk[local]+1;
                    }

                }
            }
        }
        return -1;
    }
}


编辑于 2017-03-19 11:58:30 回复(0)

热门推荐

通过挑战的用户

01翻转