【蓝桥第二周】和尚挑水

和尚挑水问题 

题目描述

某寺庙里7个和尚:轮流挑水,为了和其他任务不能冲突,各人将有空天数列出如下表:

和尚1: 星期二,四;
和尚2: 星期一,六;
和尚3: 星期三,日;
和尚4: 星期五;
和尚5: 星期一,四,六;
和尚6: 星期二,五;
和尚7: 星期三,六,日;
请将所有合理的挑水时间安排表 
样例输入:
input:
请输入和尚1的空闲时间:0 1 0 1 0 0 0
请输入和尚2的空闲时间:1 0 0 0 0 1 0
请输入和尚3的空闲时间:0 0 1 0 0 0 1
请输入和尚4的空闲时间:0 0 0 0 1 0 0
请输入和尚5的空闲时间:1 0 0 1 0 1 0
请输入和尚6的空闲时间:0 1 0 0 1 0 0
请输入和尚7的空闲时间:0 0 1 0 0 1 1

样例输出:
output:
方案1:
星期1和尚2挑水
星期2和尚6挑水
星期3和尚3挑水
星期4和尚1挑水
星期5和尚4挑水
星期6和尚5挑水
星期7和尚7挑水

方案2:
星期1和尚2挑水
星期2和尚6挑水
星期3和尚7挑水
星期4和尚1挑水
星期5和尚4挑水
星期6和尚5挑水
星期7和尚3挑水

方案3:
星期1和尚5挑水
星期2和尚6挑水
星期3和尚3挑水
星期4和尚1挑水
星期5和尚4挑水
星期6和尚2挑水
星期7和尚7挑水

方案4:
星期1和尚5挑水
星期2和尚6挑水
星期3和尚7挑水
星期4和尚1挑水
星期5和尚4挑水
星期6和尚2挑水
星期7和尚3挑水

共有4种方案

[解题思路]

       很明显的深度优先搜索,在各人有空的表中(二维数组),按天数(列)遍历,发现符合的和尚(行),因为一个和尚只挑依次水,所以标记当前行和当前列为1,表示已用。继续按天数(列)遍历,直到星期7,依次判断和尚是否有空,符合则输出,回溯。

#include<iostream>
using namespace std;
//初始化
const int N=8;
const int D=8;
int table[N][D]={ 0,0,0,0,0,0,0,0,
				  0,0,1,0,1,0,0,0,
				  0,1,0,0,0,0,1,0,
				  0,0,0,1,0,0,0,1,
				  0,0,0,0,0,1,0,0,
				  0,1,0,0,1,0,1,0,
				  0,0,1,0,0,1,0,0,
				  0,0,0,1,0,0,1,1 };
int note[N][D]={0};  //记录当前值是否可用

int ans[8];	      //每个方案的值
int sum=0;        //统计多少个方案
//完成输入
void input()	
{
	for(int i=1;i<N;i++)      //行
		for(int j=1;j<D;j++)  //列
			cin>>table[i][j];
}

//输出方案
void output_project() 
{
	cout<<"方案"<<sum<<":"<<endl;
	for(int i=1;i<N;i++)
	{
		cout<<"星期"<<i<<"和尚"<<ans[i]<<"挑水"<<endl;
	}
	cout<<endl;
}
//判断是否有时间
bool IsTime() 
{
	bool flag=true;	
	for(int i=1;i<N;i++)
	{
		if(table[ans[i]][i]==1)   ;  //避免同列,同行;
		else  
			flag=false;
	}
	return flag;
}
//递归回溯
int dfs(int week)  
{
	if(week==8) //结束标志
	{
		if(IsTime()) /*符合条件则输出*/
		{
			sum++;					//方案总数累加
			output_project();	    
		}
		return 0;
	}
	for(int i=1;i<N;i++)//行
	{
		if(note[i][week]==0)   //当前值是否符合条件 
		{
			ans[week]=i;          
			for(int k=1;k<8;k++) //标记 行:i 列:week
			{
				note[k][week]++;
				note[i][k]++;
			}
			dfs(week+1);		 //继续拓展下一天
			for(int k=1;k<8;k++)  //回溯
			{
				note[k][week]--;
				note[i][k]--;
			}
		}
	}
    return 0;
}


int main()
{
	//input();
	dfs(1);
	cout<<endl<<"共有"<<sum<<"种方案";
	getchar();
	return 0;
}
[运行结果]



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值