給定-100到100的兩個數n,m,每次只能對n加1,減1,乘2,求n變爲m的最小步數

題目:給定-100到100的兩個數n,m,每次只能對n減1,加1,乘2,求n變爲m的最小步數
例子:

n=3,m=11,需要3步從n變爲m,先乘2,再乘2,再減一

n=3,m=5,需要2步,先加1,再加1

思路:廣度優先+分支限界
因爲有3種操作,先遍歷n經過3次操作後的結果,如果結果中含有m,就只需要1步,否則就對3次操作後的結果重複此操作,再遍歷過程中用一個標記數組記錄已經處理過的數,後面再遇到就不再處理,減少了操作次數。

                                        3
                              /         |           \
                            2           4            6
                         /  |  \      /  |  \       /  |  \
                        1   3*  4*    3*  5  8     5*  7  12

從上面我們可以看出3變爲5只需要2步,就是需要遍歷2層,所以用層序遍歷即可。因爲我們是一層一層遍歷的,所以最先找到的就是最小的。

#include<iostream>
#include<queue>
using namespace std;
int flag[1000];
int step = 0;
void find(int n,int m) {
	queue<int> que;	
	que.push(n-1);	
	que.push(n+1);
	que.push(n*2);
	while (!que.empty()) {	
		int n = que.size();
		for (int i = 0; i < n;i++) {
			int val = que.front();
			que.pop();
			if (flag[val] == 1) continue;   //分支限界:如果已經處理過則不再處理
			if (val == m) {
				step++;
				return;
			}
			que.push(val- 1);
			que.push(val + 1);
			que.push(val * 2);
			flag[val] = 1;
		}
		step++;
	}
}
int main() {
	int n, m;
	while (cin>>n>>m) {
		step = 0;
		memset(flag, 0, sizeof(flag));
		flag[n] = 1;
		if (n > 0 && m > 0) {
			find(n, m);
			cout << step<<endl;
		}
		else if (n > 0 && m < 0) {
			find(n, m);
			cout << step << endl;
		}
		else if (n < 0 && m > 0) {
			find(n, m);
			cout << step << endl;
		}
		else {
			find(0-n, 0-m);
			cout << step << endl;
		}	
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章