程序設計實習MOOC / 程序設計與算法(二)測驗彙總(2019春季) 002:撥鍾問題

#include <iostream>
#include <bitset>
#include <algorithm>
#include <functional>
#include <cstring>
#include <bits/stdc++.h>
using namespace std;
int oriClocks[9];
int clocks[9];
const char * moves[9] = { "ABDE","ABC","BCEF","ADG","BDEFH","CFI","DEGH","GHI","EFHI" };
int moveTimes[9] = {0};//這個變量是用來保存9種移動方式,因爲每種方式撥4次又會回到原來的位置,所以它裏面元素的取值只有0,1,2,3。所以movetime總共有4的9次方種序列
int result[9];//這個變量是用來保存目前最好的結果的,如果遇到需要次數目前最少的,就把上面的結果複製進這個變量
int minTimes = 1 << 30;
void Enum(int n) 
{
	if( n >= 9 ) {
        //這裏n>=9表示已經完成了一次可能性的構造
		memcpy(clocks,oriClocks,sizeof(clocks));
		int totalTimes = 0;
		for( int i = 0;i < 9 ; ++ i ) { //依次進行9種移動
            //mobetimes的第i個元素值代表了第i種移動方式使用的次數
			if( moveTimes[i] ) { 
				for( int k = 0; moves[i][k]; ++k) {
					clocks[moves[i][k]-'A'] = (clocks[moves[i][k]-'A'] + moveTimes[i]) % 4;
					totalTimes += moveTimes[i];
				}
			}
		}

        //下面這個for循環是檢查是否全部回到12點的位置,如果全部回到,跳出for循環的時候i應該是9
		int i;
		for( i = 0;i < 9; ++i )
			if( clocks[i])
				break;
		if( i == 9) {
			if( minTimes > totalTimes) {
				minTimes = totalTimes;
				memcpy(result,moveTimes,sizeof(result)); 
			} 
		}
		return ;
	}

    //這個部分是使用遞歸的方法枚舉所有9個方法的組合
    //這個遞歸雖然沒錯但是比較讓人頭皮發麻,是一種不優雅的做法,用兩個循環實現會更加直觀,估計沒看懂也大多是因爲不知道遞歸的作用。
    //他的主要目的就是爲了遍歷所有的4的9次方種可能,比如101020300就代表第1,3種移動使用1次,第5,7種移動分別使用2,3次。
	for( int i = 0;i < 4; ++ i ) {
		moveTimes[n] = i;
		Enum(n+1);
	}
	return ;
} 
int main()
{
	#ifdef ONLINE_JUDGE
	#else
	freopen("in.txt", "r", stdin);
	#endif
	 
	for( int i = 0;i < 9 ; ++i )
		cin >> oriClocks[i];
	Enum(0);
	for( int i = 0; i < 9; ++i )
		for( int k = 0; k < result[i] ; ++ k ) 
			cout << i+1 << " ";
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章