【编程题】(满分32分)
某保密单位机要人员 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
分析:本题就是简单的暴搜加剪枝,每个人一周内每天有工作和休息两种情况,对于5*7的矩阵,从上到下,从左到右遍历递归,每遇到当前已经确定的作息表能进行判断的情况,就进行判断,比如,某行的数据确定,即改行代表的某人一周的作息表确定,那么据此可以进行第一个条件和最基本的条件(每周需要工作5天,休息2天),如果满足,那么继续下一行的搜索,不满足,那么这条路就结束,开始下一条路,这样就起到了剪枝的效果.源码如下:
#include<cstdlib>
#include<cstdio>
#include<iostream>
using namespace std;
int arr[5][7];
//int arr[5][7]={{0,0,1,0,1,1,1},{1,1,0,1,1,1,0},{0,1,1,0,1,1,1},{1,1,0,1,1,1,0},{1,1,1,0,1,1,0}};
int index=1;
void print()
{
printf("%d-------------\n",index++);
for(int i=0;i<5;i++)
{
for(int j=0;j<7;j++)
printf("%d",arr[i][j]);
printf("\n");
}
}
bool check()
{
int quan=0; //第二个条件,一周中,至少有3天所有人都是上班的。
for(int c=0;c<7;c++)
{
bool quanshang=true;
for(int i=0;i<5;i++)
{
if(arr[i][c]==0)
{
quanshang=false;
break;
}
}
if(quanshang==true) quan++;
}
if(quan<3) return false;
for(int c=0;c<7;c++) //第三个条件,任何一天,必须保证 A B C D 中至少有2人上班。
{
if(arr[0][c]+arr[1][c]+arr[2][c]+arr[3][c]<2) return false;
}
int ac=0; //第六个条件,A C 一周中必须至少有4天能见面(即同时上班)
for(int c=0;c<7;c++)
{
if(arr[0][c]==1 && arr[2][c]==1) ac++;
}
if(ac<4) return false;
return true;
}
bool checkhang(int hang)
{
int gong=0;
for(int c=0;c<7;c++)
{
if(arr[hang][c]==1) gong++;
}
if(gong!=5) return false;
for(int start=0;start<=6;start++)
{
if(arr[hang][start]+arr[hang][(start+1)%7]+arr[hang][(start+2)%7]+arr[hang][(start+3)%7]>=4)
return false;
}
return true;
}
void dfs(int x,int y)
{
if(y==0 && x!=0) //例如当遍历到arr[3][0]说明第三行arr[2][0]~arr[2][6]已经确定,那么进行行判断
{
if(!checkhang(x-1)) return;
}
if(x==5 && y==0) //遍历到最后一个元素arr[4][6]的下一个元素
{
if(check())
print();
return;
}
int nextx=x;
int nexty=y+1;
if(nexty>6) //一行结束
{
nextx++;//已经到行尾,则下一行
nexty=0;
}
if(y==6 && (x==1 || x==3 || x==4) )
{
arr[x][y]=0;
dfs(nextx,nexty);
}
else if(y==2 && (x==0 || x==4))
{
arr[x][y]=1;
dfs(nextx,nexty);
}
else
{
arr[x][y]=0;
dfs(nextx,nexty);
arr[x][y]=1;
dfs(nextx,nexty);
}
}
int main()
{
dfs(0,0);
return 0;
}
PS:每个月至少四篇博客,要加油~