排日程


【编程题】(满分34分)

    某保密单位机要人员 A,B,C,D,E 每周需要工作5天,休息2天。

    上级要求每个人每周的工作日和休息日安排必须是固定的,不能在周间变更。

    此外,由于工作需要,还有如下要求:

    1. 所有人的连续工作日不能多于3天(注意:周日连到下周一也是连续)。

    2. 一周中,至少有3天所有人都是上班的。

    3. 任何一天,必须保证 A B C D 中至少有2人上班。

    4. B D E 在周日那天必须休息。

    5. A E 周三必须上班。

    6. A C 一周中必须至少有4天能见面(即同时上班)。

    你的任务是:编写程序,列出ABCDE所有可能的一周排班情况。工作日记为1,休息日记为0
    
    A B C D E 每人占用1行记录,从星期一开始。

【输入、输出格式要求】

    程序没有输入,要求输出所有可能的方案。

    每个方案是7x5的矩阵。只有1和0组成。        
    
    矩阵中的列表示星期几,从星期一开始。

    矩阵的行分别表示A,B,C,D,E的作息时间表。

    多个矩阵间用空行分隔开。

    例如,如下的矩阵就是一个合格的解。请编程输出所有解(多个解的前后顺序不重要)。

0110111
1101110
0110111
1101110
1110110

【注意】

    请仔细调试!您的程序只有能运行出正确结果的时候才有机会得分!
    
    请把所有类写在同一个文件中,调试好后,存入与【考生文件夹】下对应题号的“解答.txt”中即可。
    
    相关的工程文件不要拷入。
    
    请不要使用package语句。
    

    源程序中只能出现JDK1.5中允许的语法或调用。不能使用1.6或更高版本。


问题分析:dfs搜就行,不过要加添加各种条件以及剪枝

#include<bits/stdc++.h>
using namespace std;

int a[5][7];

void print()
{
	for(int i = 0; i < 5; i++){
		for(int j = 0; j < 7; j++){
			printf("%d%c",a[i][j],j==6?10:32);
		}
	}
	cout << endl;
}

bool check()
{
	//一周中,至少有3天所有人都是上班的
	int cnt = 0;
	for(int i = 0; i < 7; i++){
		if (a[0][i] + a[1][i] + a[2][i] + a[3][i] + a[4][i] == 5)
			cnt++;
	}
	if (cnt < 3)
		return false;
	//任何一天,必须保证 A B C D 中至少有2人上班。
	//即任何一天,工作人数>=2 
	for(int i = 0; i < 7; i++){
		if (a[0][i] + a[1][i] + a[2][i] + a[3][i] < 2)
			return false;
	}
	
	//A C 一周中必须至少有4天能见面(即同时上班)。
	int cm = 0;
	for(int i = 0; i < 7; i++){
		if (a[0][i] == 1 && a[2][i] == 1)
			cm++;
	}
	if (cm < 4)	return false;
	return true;
}

bool checkrow(int x)
{
	int workday = 0;
	
	for(int i = 0; i < 7; i++){	
		if (a[x][i] == 1)
			workday++;
	}
	if (workday != 5)	// 每周需要工作5天
		return false;
	
	
	//所有人的连续工作日不能多于3天(注意:周日连到下周一也是连续) 
	for(int i = 0; i < 7; i++){
		if (a[x][i] == 1 && a[x][(i+1)%7] == 1 && a[x][(i+2)%7] == 1 && a[x][(i+3)%7] == 1)
			return false;
	}
	return true;
}


void dfs(int x,int y)
{
	if (y == 0 && x != 0){
		if (checkrow(x-1) == false)
			return;
	}
	
	if (x == 5 && y == 0){
		if (check())
			print();
		return;
	}
	
	if (y == 7){
		dfs(x+1,0);
	}
	//B D E 在周日那天必须休息
	else if (y == 6 && (x == 1 || x == 3 || x == 4)){
		a[x][y] = 0;
		dfs(x+1,0);
	}
	//A E 周三必须上班
	else if (y == 2 && (x == 0 || x == 4)){
		a[x][y] = 1;
		dfs(x,y+1);
	}
	else{
		a[x][y] = 0;
		dfs(x,y+1);
		a[x][y] = 1;
		dfs(x,y+1);
	}
}

int main()
{
	dfs(0,0);
	return 0;	
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值