華爲機試:和尚挑水問題

問題描述:

某寺廟裏7個和尚:輪流挑水,爲了和其他任務不能衝突,各人將有空天數列出如下表:
和尚1: 星期二,四;
和尚2: 星期一,六;
和尚3: 星期三,日;
和尚4: 星期五;
和尚5: 星期一,四,六;
和尚6: 星期二,五;
和尚7: 星期三,六,日;
請將所有合理的挑水時間安排表 

輸入7行7列,0代表和尚今天不挑水,1代表可以挑水,A和尚挑完水本週就不挑了,問有多少種挑水方法,排列組合是什麼。

這題比較糾結的是如何先輸出挑水的總數,然後輸出挑水的安排。如果用回溯法進行遞歸的話,只能count++或者輸出滿足條件的情況,但是肯定不能先輸出總是再輸出安排。我能想到就是比較笨的方法,同一種方法使用兩次,這裏就不寫那種方法了,只寫輸出安排,最後輸出總數的方法,有好方法的話還望賜教。

回到本題,用回溯法做比較方便,週一選出一個合適的和尚,再週二選合適的和尚,直到週末,這個合適指的是和尚該天可以挑水而且之前沒挑過,可以用兩個數組存放其狀態,狀態符合的話就往下走。用遞歸和for循環實現遍歷所以情況,判斷是否適合。程序代碼如下:

#include <iostream>
#define day 8
using namespace std;

int spare[day][day];
int count;
int monk[day];//週一至週末值日的和尚
int done[day];//用來存放和尚在星期day是否值日過
/*
void getNum(int t){
	if(t>=day)	{
		count++;
	}
	else{
		for(int i=1;i<day;i++){
			monk[t]=i;
			if(done[i]==0 && spare[i][t]==1){
				done[i]=1;
				getNum(t+1);
				done[i]=0;
			}
		}
	}
}
*/
void printmonk(int t){
	if(t>=day){
		for(int i=1;i<day;i++){
			cout<<monk[i]<<" ";
		}
		cout<<endl;
		count++;
	}
	else{
		for(int i=1;i<day;i++){
			monk[t]=i;
			if(done[i]==0 && spare[i][t]==1){
				done[i]=1;
				printmonk(t+1);
				done[i]=0;
			}
		}
	}
}
int main(){

	count=0;
	for(int i=1;i<day;i++)
		for(int j=1;j<day;j++)
			cin>>spare[i][j];
	for(int i=1;i<day;i++){
		monk[i]=0;
		done[i]=0;
	}
	printmonk(1);
	cout<<count<<endl;
	//getNum(1);
	/*
	cout<<count<<endl;
	for(int i=1;i<day;i++){
		monk[i]=0;
		done[i]=0;
	}
	printmonk(1);
	*/
	return 0;
}


如有問題,希望提出。

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